Files
app_Settings/src/com/android/settings/notification/SoundWorkSettingsController.java
Cole Faust 43ff89802c Fix errorprone warnings that should be errors
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
2022-10-23 12:41:39 -07:00

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();
}
}
}
}