This commit is part of a large scale change to fix errorprone errors that have been downgraded to warnings in the android source tree, so that they can be promoted to errors again. The full list of changes include the following, but not all will be present in any one individual commit: BadAnnotationImplementation BadShiftAmount BanJNDI BoxedPrimitiveEquality ComparableType ComplexBooleanConstant CollectionToArraySafeParameter ConditionalExpressionNumericPromotion DangerousLiteralNull DoubleBraceInitialization DurationFrom DurationTemporalUnit EmptyTopLevelDeclaration EqualsNull EqualsReference FormatString FromTemporalAccessor GetClassOnAnnotation GetClassOnClass HashtableContains IdentityBinaryExpression IdentityHashMapBoxing InstantTemporalUnit InvalidTimeZoneID InvalidZoneId IsInstanceIncompatibleType JUnitParameterMethodNotFound LockOnBoxedPrimitive MathRoundIntLong MislabeledAndroidString MisusedDayOfYear MissingSuperCall MisusedWeekYear ModifyingCollectionWithItself NoCanIgnoreReturnValueOnClasses NonRuntimeAnnotation NullableOnContainingClass NullTernary OverridesJavaxInjectableMethod ParcelableCreator PeriodFrom PreconditionsInvalidPlaceholder ProtoBuilderReturnValueIgnored ProtoFieldNullComparison RandomModInteger RectIntersectReturnValueIgnored ReturnValueIgnored SelfAssignment SelfComparison SelfEquals SizeGreaterThanOrEqualsZero StringBuilderInitWithChar TreeToString TryFailThrowable UnnecessaryCheckNotNull UnusedCollectionModifiedInPlace XorPower See https://errorprone.info/bugpatterns for more information on the checks. Bug: 253827323 Test: m RUN_ERROR_PRONE=true javac-check Change-Id: I29f691a22617b1fc834680ff1cf4ab4244203f06
379 lines
15 KiB
Java
379 lines
15 KiB
Java
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.notification;
|
|
|
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_MESSAGE;
|
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_TITLE;
|
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_ACTIVE_SUMMARY;
|
|
|
|
import android.annotation.UserIdInt;
|
|
import android.app.Dialog;
|
|
import android.app.admin.DevicePolicyManager;
|
|
import android.app.settings.SettingsEnums;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.media.Ringtone;
|
|
import android.media.RingtoneManager;
|
|
import android.net.Uri;
|
|
import android.os.Bundle;
|
|
import android.os.UserHandle;
|
|
import android.os.UserManager;
|
|
import android.provider.Settings;
|
|
|
|
import androidx.annotation.VisibleForTesting;
|
|
import androidx.appcompat.app.AlertDialog;
|
|
import androidx.fragment.app.FragmentManager;
|
|
import androidx.preference.Preference;
|
|
import androidx.preference.PreferenceGroup;
|
|
import androidx.preference.PreferenceScreen;
|
|
import androidx.preference.TwoStatePreference;
|
|
|
|
import com.android.settings.DefaultRingtonePreference;
|
|
import com.android.settings.R;
|
|
import com.android.settings.Utils;
|
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
|
import com.android.settingslib.core.AbstractPreferenceController;
|
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
|
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
|
import com.android.settingslib.core.lifecycle.events.OnPause;
|
|
import com.android.settingslib.core.lifecycle.events.OnResume;
|
|
|
|
/** Controller that manages the Sounds settings relevant preferences for work profile. */
|
|
public class SoundWorkSettingsController extends AbstractPreferenceController
|
|
implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
|
|
|
|
private static final String TAG = "SoundWorkSettingsController";
|
|
private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds";
|
|
private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone";
|
|
private static final String KEY_WORK_NOTIFICATION_RINGTONE = "work_notification_ringtone";
|
|
private static final String KEY_WORK_ALARM_RINGTONE = "work_alarm_ringtone";
|
|
|
|
private final boolean mVoiceCapable;
|
|
private final UserManager mUserManager;
|
|
private final SoundWorkSettings mParent;
|
|
private final AudioHelper mHelper;
|
|
|
|
private TwoStatePreference mWorkUsePersonalSounds;
|
|
private Preference mWorkPhoneRingtonePreference;
|
|
private Preference mWorkNotificationRingtonePreference;
|
|
private Preference mWorkAlarmRingtonePreference;
|
|
private PreferenceScreen mScreen;
|
|
|
|
@UserIdInt
|
|
private int mManagedProfileId;
|
|
private final BroadcastReceiver mManagedProfileReceiver = new BroadcastReceiver() {
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
final int userId = ((UserHandle) intent.getExtra(Intent.EXTRA_USER)).getIdentifier();
|
|
switch (intent.getAction()) {
|
|
case Intent.ACTION_MANAGED_PROFILE_ADDED: {
|
|
onManagedProfileAdded(userId);
|
|
return;
|
|
}
|
|
case Intent.ACTION_MANAGED_PROFILE_REMOVED: {
|
|
onManagedProfileRemoved(userId);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
public SoundWorkSettingsController(Context context, SoundWorkSettings parent,
|
|
Lifecycle lifecycle) {
|
|
this(context, parent, lifecycle, new AudioHelper(context));
|
|
}
|
|
|
|
@VisibleForTesting
|
|
SoundWorkSettingsController(Context context, SoundWorkSettings parent, Lifecycle lifecycle,
|
|
AudioHelper helper) {
|
|
super(context);
|
|
mUserManager = UserManager.get(context);
|
|
mVoiceCapable = Utils.isVoiceCapable(mContext);
|
|
mParent = parent;
|
|
mHelper = helper;
|
|
if (lifecycle != null) {
|
|
lifecycle.addObserver(this);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void displayPreference(PreferenceScreen screen) {
|
|
super.displayPreference(screen);
|
|
mScreen = screen;
|
|
}
|
|
|
|
@Override
|
|
public void onResume() {
|
|
IntentFilter managedProfileFilter = new IntentFilter();
|
|
managedProfileFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
|
|
managedProfileFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
|
|
mContext.registerReceiver(mManagedProfileReceiver, managedProfileFilter);
|
|
mManagedProfileId = mHelper.getManagedProfileId(mUserManager);
|
|
updateWorkPreferences();
|
|
}
|
|
|
|
@Override
|
|
public void onPause() {
|
|
mContext.unregisterReceiver(mManagedProfileReceiver);
|
|
}
|
|
|
|
@Override
|
|
public boolean isAvailable() {
|
|
return mHelper.getManagedProfileId(mUserManager) != UserHandle.USER_NULL
|
|
&& shouldShowRingtoneSettings();
|
|
}
|
|
|
|
@Override
|
|
public boolean handlePreferenceTreeClick(Preference preference) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public String getPreferenceKey() {
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Updates the summary of work preferences
|
|
*
|
|
* This controller listens to changes on the work ringtone preferences, identified by keys
|
|
* "work_ringtone", "work_notification_ringtone" and "work_alarm_ringtone".
|
|
*/
|
|
@Override
|
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
int ringtoneType;
|
|
if (KEY_WORK_PHONE_RINGTONE.equals(preference.getKey())) {
|
|
ringtoneType = RingtoneManager.TYPE_RINGTONE;
|
|
} else if (KEY_WORK_NOTIFICATION_RINGTONE.equals(preference.getKey())) {
|
|
ringtoneType = RingtoneManager.TYPE_NOTIFICATION;
|
|
} else if (KEY_WORK_ALARM_RINGTONE.equals(preference.getKey())) {
|
|
ringtoneType = RingtoneManager.TYPE_ALARM;
|
|
} else {
|
|
return true;
|
|
}
|
|
|
|
preference.setSummary(updateRingtoneName(getManagedProfileContext(), ringtoneType));
|
|
return true;
|
|
}
|
|
|
|
private boolean shouldShowRingtoneSettings() {
|
|
return !mHelper.isSingleVolume();
|
|
}
|
|
|
|
private CharSequence updateRingtoneName(Context context, int type) {
|
|
if (context == null || !mHelper.isUserUnlocked(mUserManager, context.getUserId())) {
|
|
return mContext.getString(R.string.managed_profile_not_available_label);
|
|
}
|
|
Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
|
|
return Ringtone.getTitle(context, ringtoneUri, false /* followSettingsUri */,
|
|
/* allowRemote= */ true);
|
|
}
|
|
|
|
private Context getManagedProfileContext() {
|
|
if (mManagedProfileId == UserHandle.USER_NULL) {
|
|
return null;
|
|
}
|
|
return mHelper.createPackageContextAsUser(mManagedProfileId);
|
|
}
|
|
|
|
private DefaultRingtonePreference initWorkPreference(PreferenceGroup root, String key) {
|
|
final DefaultRingtonePreference pref = root.findPreference(key);
|
|
pref.setOnPreferenceChangeListener(this);
|
|
|
|
// Required so that RingtonePickerActivity lists the work profile ringtones
|
|
pref.setUserId(mManagedProfileId);
|
|
return pref;
|
|
}
|
|
|
|
private void updateWorkPreferences() {
|
|
if (!isAvailable()) {
|
|
return;
|
|
}
|
|
|
|
if (mWorkUsePersonalSounds == null) {
|
|
mWorkUsePersonalSounds = mScreen.findPreference(KEY_WORK_USE_PERSONAL_SOUNDS);
|
|
mWorkUsePersonalSounds.setOnPreferenceChangeListener((Preference p, Object value) -> {
|
|
if ((boolean) value) {
|
|
SoundWorkSettingsController.UnifyWorkDialogFragment.show(mParent);
|
|
return false;
|
|
} else {
|
|
disableWorkSync();
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (mWorkPhoneRingtonePreference == null) {
|
|
mWorkPhoneRingtonePreference = initWorkPreference(mScreen,
|
|
KEY_WORK_PHONE_RINGTONE);
|
|
}
|
|
|
|
if (mWorkNotificationRingtonePreference == null) {
|
|
mWorkNotificationRingtonePreference = initWorkPreference(mScreen,
|
|
KEY_WORK_NOTIFICATION_RINGTONE);
|
|
}
|
|
|
|
if (mWorkAlarmRingtonePreference == null) {
|
|
mWorkAlarmRingtonePreference = initWorkPreference(mScreen,
|
|
KEY_WORK_ALARM_RINGTONE);
|
|
}
|
|
|
|
if (!mVoiceCapable) {
|
|
mWorkPhoneRingtonePreference.setVisible(false);
|
|
mWorkPhoneRingtonePreference = null;
|
|
}
|
|
|
|
if (Settings.Secure.getIntForUser(getManagedProfileContext().getContentResolver(),
|
|
Settings.Secure.SYNC_PARENT_SOUNDS, /* def= */ 0, mManagedProfileId) == 1) {
|
|
enableWorkSyncSettings();
|
|
} else {
|
|
disableWorkSyncSettings();
|
|
}
|
|
}
|
|
|
|
void enableWorkSync() {
|
|
Settings.Secure.putIntForUser(getManagedProfileContext().getContentResolver(),
|
|
Settings.Secure.SYNC_PARENT_SOUNDS, /* enabled= */ 1, mManagedProfileId);
|
|
enableWorkSyncSettings();
|
|
}
|
|
|
|
private void enableWorkSyncSettings() {
|
|
mWorkUsePersonalSounds.setChecked(true);
|
|
|
|
String summary = mContext.getSystemService(DevicePolicyManager.class).getResources()
|
|
.getString(WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_ACTIVE_SUMMARY,
|
|
() -> mContext.getString(R.string.work_sound_same_as_personal)
|
|
);
|
|
|
|
if (mWorkPhoneRingtonePreference != null) {
|
|
mWorkPhoneRingtonePreference.setSummary(summary);
|
|
}
|
|
mWorkNotificationRingtonePreference.setSummary(summary);
|
|
mWorkAlarmRingtonePreference.setSummary(summary);
|
|
}
|
|
|
|
private void disableWorkSync() {
|
|
Settings.Secure.putIntForUser(getManagedProfileContext().getContentResolver(),
|
|
Settings.Secure.SYNC_PARENT_SOUNDS, /* enabled= */ 0, mManagedProfileId);
|
|
disableWorkSyncSettings();
|
|
}
|
|
|
|
private void disableWorkSyncSettings() {
|
|
if (mWorkPhoneRingtonePreference != null) {
|
|
mWorkPhoneRingtonePreference.setEnabled(true);
|
|
}
|
|
mWorkNotificationRingtonePreference.setEnabled(true);
|
|
mWorkAlarmRingtonePreference.setEnabled(true);
|
|
|
|
updateWorkRingtoneSummaries();
|
|
}
|
|
|
|
private void updateWorkRingtoneSummaries() {
|
|
Context managedProfileContext = getManagedProfileContext();
|
|
|
|
if (mWorkPhoneRingtonePreference != null) {
|
|
mWorkPhoneRingtonePreference.setSummary(
|
|
updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_RINGTONE));
|
|
}
|
|
mWorkNotificationRingtonePreference.setSummary(
|
|
updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_NOTIFICATION));
|
|
mWorkAlarmRingtonePreference.setSummary(
|
|
updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_ALARM));
|
|
}
|
|
|
|
/**
|
|
* Update work preferences if work profile added.
|
|
* @param profileId the profile identifier.
|
|
*/
|
|
public void onManagedProfileAdded(@UserIdInt int profileId) {
|
|
if (mManagedProfileId == UserHandle.USER_NULL) {
|
|
mManagedProfileId = profileId;
|
|
updateWorkPreferences();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update work preferences if work profile removed.
|
|
* @param profileId the profile identifier.
|
|
*/
|
|
public void onManagedProfileRemoved(@UserIdInt int profileId) {
|
|
if (mManagedProfileId == profileId) {
|
|
mManagedProfileId = mHelper.getManagedProfileId(mUserManager);
|
|
updateWorkPreferences();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dialog to confirm with the user if it's ok to use the personal profile sounds as the work
|
|
* profile sounds.
|
|
*/
|
|
public static class UnifyWorkDialogFragment extends InstrumentedDialogFragment
|
|
implements DialogInterface.OnClickListener {
|
|
private static final String TAG = "UnifyWorkDialogFragment";
|
|
private static final int REQUEST_CODE = 200;
|
|
|
|
/**
|
|
* Show dialog that allows to use the personal profile sounds as the work profile sounds.
|
|
* @param parent SoundWorkSettings fragment.
|
|
*/
|
|
public static void show(SoundWorkSettings parent) {
|
|
FragmentManager fm = parent.getFragmentManager();
|
|
if (fm.findFragmentByTag(TAG) == null) {
|
|
UnifyWorkDialogFragment fragment = new UnifyWorkDialogFragment();
|
|
fragment.setTargetFragment(parent, REQUEST_CODE);
|
|
fragment.show(fm, TAG);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getMetricsCategory() {
|
|
return SettingsEnums.DIALOG_UNIFY_SOUND_SETTINGS;
|
|
}
|
|
|
|
@Override
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
|
|
Context context = getActivity().getApplicationContext();
|
|
DevicePolicyManager devicePolicyManager =
|
|
context.getSystemService(DevicePolicyManager.class);
|
|
|
|
return new AlertDialog.Builder(getActivity())
|
|
.setTitle(devicePolicyManager.getResources().getString(
|
|
ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_TITLE,
|
|
() -> context.getString(R.string.work_sync_dialog_title)))
|
|
.setMessage(devicePolicyManager.getResources().getString(
|
|
ENABLE_WORK_PROFILE_SYNC_WITH_PERSONAL_SOUNDS_DIALOG_MESSAGE,
|
|
() -> context.getString(R.string.work_sync_dialog_message)))
|
|
.setPositiveButton(R.string.work_sync_dialog_yes,
|
|
SoundWorkSettingsController.UnifyWorkDialogFragment.this)
|
|
.setNegativeButton(android.R.string.cancel, /* listener= */ null)
|
|
.create();
|
|
}
|
|
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
SoundWorkSettings soundWorkSettings = (SoundWorkSettings) getTargetFragment();
|
|
if (soundWorkSettings.isAdded()) {
|
|
soundWorkSettings.enableWorkSync();
|
|
}
|
|
}
|
|
}
|
|
}
|