summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/RingerModeTracker.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt89
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java105
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java44
14 files changed, 517 insertions, 88 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 88d6943b4071..367058fa58dd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -57,7 +57,6 @@ import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
-import android.media.AudioManager;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IRemoteCallback;
@@ -82,6 +81,8 @@ import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import androidx.lifecycle.Observer;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils;
import com.android.settingslib.WirelessUtils;
@@ -97,6 +98,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.util.Assert;
+import com.android.systemui.util.RingerModeTracker;
import com.google.android.collect.Lists;
@@ -258,6 +260,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private TrustManager mTrustManager;
private UserManager mUserManager;
private KeyguardBypassController mKeyguardBypassController;
+ private RingerModeTracker mRingerModeTracker;
private int mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
private int mFaceRunningState = BIOMETRIC_STATE_STOPPED;
private LockPatternUtils mLockPatternUtils;
@@ -295,6 +298,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private final Handler mHandler;
+ private final Observer<Integer> mRingerModeObserver = new Observer<Integer>() {
+ @Override
+ public void onChanged(Integer ringer) {
+ mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED, ringer, 0).sendToTarget();
+ }
+ };
+
private SparseBooleanArray mFaceSettingEnabledForUser = new SparseBooleanArray();
private BiometricManager mBiometricManager;
private IBiometricEnabledOnKeyguardCallback mBiometricEnabledCallback =
@@ -1145,9 +1155,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
.sendToTarget();
- } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
- intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
} else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
@@ -1501,6 +1508,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mUserTrustIsUsuallyManaged.delete(userId);
}
+ private void registerRingerTracker() {
+ mRingerModeTracker.getRingerMode().observeForever(mRingerModeObserver);
+ }
+
@VisibleForTesting
@Inject
protected KeyguardUpdateMonitor(
@@ -1508,6 +1519,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@Main Looper mainLooper,
BroadcastDispatcher broadcastDispatcher,
DumpManager dumpManager,
+ RingerModeTracker ringerModeTracker,
@Background Executor backgroundExecutor) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
@@ -1515,6 +1527,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged);
mBackgroundExecutor = backgroundExecutor;
mBroadcastDispatcher = broadcastDispatcher;
+ mRingerModeTracker = ringerModeTracker;
dumpManager.registerDumpable(getClass().getName(), this);
mHandler = new Handler(mainLooper) {
@@ -1648,10 +1661,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
filter.addAction(Intent.ACTION_SERVICE_STATE);
filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
mBroadcastDispatcher.registerReceiverWithHandler(mBroadcastReceiver, filter, mHandler);
+ mHandler.post(this::registerRingerTracker);
+
final IntentFilter allUserFilter = new IntentFilter();
allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
@@ -2802,6 +2816,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
mBroadcastDispatcher.unregisterReceiver(mBroadcastAllReceiver);
+ mRingerModeTracker.getRingerMode().removeObserver(mRingerModeObserver);
mHandler.removeCallbacksAndMessages(null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
index 5b3d5c565472..82ccb17a52c6 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
@@ -74,6 +74,8 @@ import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerServiceImpl;
+import com.android.systemui.util.RingerModeTracker;
+import com.android.systemui.util.RingerModeTrackerImpl;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.volume.VolumeDialogComponent;
import com.android.systemui.volume.VolumeDialogControllerImpl;
@@ -264,4 +266,10 @@ public abstract class DependencyBinder {
@Binds
public abstract VolumeComponent provideVolumeComponent(
VolumeDialogComponent volumeDialogComponent);
+
+ /**
+ */
+ @Binds
+ public abstract RingerModeTracker provideRingerModeTracker(
+ RingerModeTrackerImpl ringerModeTrackerImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index f5293ccf0b0f..5aed64793711 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -78,6 +78,11 @@ import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
@@ -114,6 +119,7 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.EmergencyDialerConstants;
+import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.leak.RotationUtils;
import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
@@ -130,7 +136,8 @@ import javax.inject.Inject;
public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
DialogInterface.OnShowListener,
ConfigurationController.ConfigurationListener,
- GlobalActionsPanelPlugin.Callbacks {
+ GlobalActionsPanelPlugin.Callbacks,
+ LifecycleOwner {
public static final String SYSTEM_DIALOG_REASON_KEY = "reason";
public static final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
@@ -179,6 +186,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private final NotificationShadeDepthController mDepthController;
private final BlurUtils mBlurUtils;
+ // Used for RingerModeTracker
+ private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
+
private ArrayList<Action> mItems;
private ActionsDialog mDialog;
@@ -209,6 +219,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private List<ControlsServiceInfo> mControlsServiceInfos = new ArrayList<>();
private ControlsController mControlsController;
private SharedPreferences mControlsPreferences;
+ private final RingerModeTracker mRingerModeTracker;
@VisibleForTesting
public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
@@ -247,7 +258,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
ControlsUiController controlsUiController, IWindowManager iWindowManager,
@Background Executor backgroundExecutor,
ControlsListingController controlsListingController,
- ControlsController controlsController, UiEventLogger uiEventLogger) {
+ ControlsController controlsController, UiEventLogger uiEventLogger,
+ RingerModeTracker ringerModeTracker) {
mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
mWindowManagerFuncs = windowManagerFuncs;
mAudioManager = audioManager;
@@ -274,6 +286,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mBackgroundExecutor = backgroundExecutor;
mControlsListingController = controlsListingController;
mBlurUtils = blurUtils;
+ mRingerModeTracker = ringerModeTracker;
mControlsController = controlsController;
// receive broadcasts
@@ -294,6 +307,11 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mShowSilentToggle = SHOW_SILENT_TOGGLE && !resources.getBoolean(
R.bool.config_useFixedVolume);
+ if (mShowSilentToggle) {
+ mRingerModeTracker.getRingerMode().observe(this, ringer ->
+ mHandler.sendEmptyMessage(MESSAGE_REFRESH)
+ );
+ }
mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
mScreenshotHelper = new ScreenshotHelper(context);
@@ -1001,16 +1019,13 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
refreshSilentMode();
mAirplaneModeOn.updateState(mAirplaneState);
mAdapter.notifyDataSetChanged();
- if (mShowSilentToggle) {
- IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
- mBroadcastDispatcher.registerReceiver(mRingerModeReceiver, filter);
- }
+ mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
}
private void refreshSilentMode() {
if (!mHasVibrator) {
- final boolean silentModeOn =
- mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
+ Integer value = mRingerModeTracker.getRingerMode().getValue();
+ final boolean silentModeOn = value != null && value != AudioManager.RINGER_MODE_NORMAL;
((ToggleAction) mSilentModeAction).updateState(
silentModeOn ? ToggleState.On : ToggleState.Off);
}
@@ -1024,14 +1039,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mDialog = null;
}
mWindowManagerFuncs.onGlobalActionsHidden();
- if (mShowSilentToggle) {
- try {
- mBroadcastDispatcher.unregisterReceiver(mRingerModeReceiver);
- } catch (IllegalArgumentException ie) {
- // ignore this
- Log.w(TAG, ie);
- }
- }
+ mLifecycle.setCurrentState(Lifecycle.State.DESTROYED);
}
/**
@@ -1578,15 +1586,6 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
};
- private BroadcastReceiver mRingerModeReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
- mHandler.sendEmptyMessage(MESSAGE_REFRESH);
- }
- }
- };
-
private ContentObserver mAirplaneModeObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
@@ -1652,6 +1651,12 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
}
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycle;
+ }
+
private static final class ActionsDialog extends Dialog implements DialogInterface,
ColorExtractor.OnColorsChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index e1ffad4df2c3..90dc38f3ad12 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -22,10 +22,8 @@ import static com.android.systemui.util.Utils.useQsMediaPlayer;
import android.annotation.ColorInt;
import android.app.ActivityManager;
import android.app.AlarmManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -49,13 +47,16 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DualToneHandler;
import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
@@ -70,6 +71,7 @@ import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.RingerModeTracker;
import java.util.ArrayList;
import java.util.List;
@@ -86,7 +88,7 @@ import javax.inject.Named;
*/
public class QuickStatusBarHeader extends RelativeLayout implements
View.OnClickListener, NextAlarmController.NextAlarmChangeCallback,
- ZenModeController.Callback {
+ ZenModeController.Callback, LifecycleOwner {
private static final String TAG = "QuickStatusBarHeader";
private static final boolean DEBUG = false;
@@ -137,15 +139,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements
private DateView mDateView;
private BatteryMeterView mBatteryRemainingIcon;
- private BroadcastDispatcher mBroadcastDispatcher;
+ // Used for RingerModeTracker
+ private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
- private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- mRingerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
- updateStatusText();
- }
- };
private boolean mHasTopCutout = false;
private int mRoundedCornerPadding = 0;
@@ -154,7 +150,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
NextAlarmController nextAlarmController, ZenModeController zenModeController,
StatusBarIconController statusBarIconController,
ActivityStarter activityStarter,
- CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher) {
+ CommandQueue commandQueue, RingerModeTracker ringerModeTracker) {
super(context, attrs);
mAlarmController = nextAlarmController;
mZenController = zenModeController;
@@ -162,8 +158,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mActivityStarter = activityStarter;
mDualToneHandler = new DualToneHandler(
new ContextThemeWrapper(context, R.style.QSHeaderTheme));
- mBroadcastDispatcher = broadcastDispatcher;
mCommandQueue = commandQueue;
+ ringerModeTracker.getRingerModeInternal().observe(this, ringer -> {
+ mRingerMode = ringer;
+ updateStatusText();
+ });
}
@Override
@@ -484,12 +483,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements
if (listening) {
mZenController.addCallback(this);
mAlarmController.addCallback(this);
- mBroadcastDispatcher.registerReceiver(mRingerReceiver,
- new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+ mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
} else {
mZenController.removeCallback(this);
mAlarmController.removeCallback(this);
- mBroadcastDispatcher.unregisterReceiver(mRingerReceiver);
+ mLifecycle.setCurrentState(Lifecycle.State.DESTROYED);
}
}
@@ -586,4 +584,10 @@ public class QuickStatusBarHeader extends RelativeLayout implements
lp.rightMargin = sideMargins;
}
}
+
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycle;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 14af466a2424..d4f4d3bfbb54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -39,6 +39,8 @@ import android.telecom.TelecomManager;
import android.text.format.DateFormat;
import android.util.Log;
+import androidx.lifecycle.Observer;
+
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.DisplayId;
@@ -64,6 +66,7 @@ import com.android.systemui.statusbar.policy.RotationLockController.RotationLock
import com.android.systemui.statusbar.policy.SensorPrivacyController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.time.DateFormatUtil;
import java.util.Locale;
@@ -109,7 +112,6 @@ public class PhoneStatusBarPolicy
private final SharedPreferences mSharedPreferences;
private final DateFormatUtil mDateFormatUtil;
private final TelecomManager mTelecomManager;
- private final AudioManager mAudioManager;
private final Handler mHandler = new Handler();
private final CastController mCast;
@@ -132,6 +134,7 @@ public class PhoneStatusBarPolicy
private final Executor mUiBgExecutor;
private final SensorPrivacyController mSensorPrivacyController;
private final RecordingController mRecordingController;
+ private final RingerModeTracker mRingerModeTracker;
private boolean mZenVisible;
private boolean mVolumeVisible;
@@ -154,10 +157,11 @@ public class PhoneStatusBarPolicy
KeyguardStateController keyguardStateController,
LocationController locationController,
SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager,
- AlarmManager alarmManager, UserManager userManager, AudioManager audioManager,
+ AlarmManager alarmManager, UserManager userManager,
RecordingController recordingController,
@Nullable TelecomManager telecomManager, @DisplayId int displayId,
- @Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil) {
+ @Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
+ RingerModeTracker ringerModeTracker) {
mIconController = iconController;
mCommandQueue = commandQueue;
mBroadcastDispatcher = broadcastDispatcher;
@@ -179,8 +183,8 @@ public class PhoneStatusBarPolicy
mSensorPrivacyController = sensorPrivacyController;
mRecordingController = recordingController;
mUiBgExecutor = uiBgExecutor;
- mAudioManager = audioManager;
mTelecomManager = telecomManager;
+ mRingerModeTracker = ringerModeTracker;
mSlotCast = resources.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = resources.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -208,8 +212,7 @@ public class PhoneStatusBarPolicy
public void init() {
// listen for broadcasts
IntentFilter filter = new IntentFilter();
- filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
- filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
+
filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
@@ -217,6 +220,10 @@ public class PhoneStatusBarPolicy
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
mBroadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, mHandler);
+ Observer<Integer> observer = ringer -> mHandler.post(this::updateVolumeZen);
+
+ mRingerModeTracker.getRingerMode().observeForever(observer);
+ mRingerModeTracker.getRingerModeInternal().observeForever(observer);
// listen for user / profile change.
try {
@@ -350,14 +357,18 @@ public class PhoneStatusBarPolicy
}
if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConsolidatedPolicy())) {
- if (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
- volumeVisible = true;
- volumeIconId = R.drawable.stat_sys_ringer_vibrate;
- volumeDescription = mResources.getString(R.string.accessibility_ringer_vibrate);
- } else if (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
- volumeVisible = true;
- volumeIconId = R.drawable.stat_sys_ringer_silent;
- volumeDescription = mResources.getString(R.string.accessibility_ringer_silent);
+ final Integer ringerModeInternal =
+ mRingerModeTracker.getRingerModeInternal().getValue();
+ if (ringerModeInternal != null) {
+ if (ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
+ volumeVisible = true;
+ volumeIconId = R.drawable.stat_sys_ringer_vibrate;
+ volumeDescription = mResources.getString(R.string.accessibility_ringer_vibrate);
+ } else if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
+ volumeVisible = true;
+ volumeIconId = R.drawable.stat_sys_ringer_silent;
+ volumeDescription = mResources.getString(R.string.accessibility_ringer_silent);
+ }
}
}
@@ -616,10 +627,6 @@ public class PhoneStatusBarPolicy
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
- case AudioManager.RINGER_MODE_CHANGED_ACTION:
- case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION:
- updateVolumeZen();
- break;
case Intent.ACTION_SIM_STATE_CHANGED:
// Avoid rebroadcast because SysUI is direct boot aware.
if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/RingerModeTracker.kt b/packages/SystemUI/src/com/android/systemui/util/RingerModeTracker.kt
new file mode 100644
index 000000000000..047298e6ed81
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/RingerModeTracker.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2020 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.systemui.util
+
+import androidx.lifecycle.LiveData
+
+interface RingerModeTracker {
+
+ val ringerMode: LiveData<Int>
+ val ringerModeInternal: LiveData<Int>
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt
new file mode 100644
index 000000000000..58684c386995
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 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.systemui.util
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.media.AudioManager
+import android.os.UserHandle
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.qualifiers.Background
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class RingerModeTrackerImpl @Inject constructor(
+ audioManager: AudioManager,
+ broadcastDispatcher: BroadcastDispatcher,
+ @Background executor: Executor
+) : RingerModeTracker {
+
+ override val ringerMode: LiveData<Int> = RingerModeLiveData(
+ broadcastDispatcher,
+ executor,
+ AudioManager.RINGER_MODE_CHANGED_ACTION,
+ audioManager::getRingerMode
+ )
+
+ override val ringerModeInternal: LiveData<Int> = RingerModeLiveData(
+ broadcastDispatcher,
+ executor,
+ AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION,
+ audioManager::getRingerModeInternal
+ )
+}
+
+class RingerModeLiveData(
+ private val broadcastDispatcher: BroadcastDispatcher,
+ private val executor: Executor,
+ intent: String,
+ private val getter: () -> Int
+) : MutableLiveData<Int>() {
+
+ private val filter = IntentFilter(intent)
+ var initialSticky: Boolean = false
+ private set
+
+ private val receiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ initialSticky = isInitialStickyBroadcast
+ postValue(intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1))
+ }
+ }
+
+ override fun getValue(): Int {
+ return super.getValue() ?: -1
+ }
+
+ override fun onActive() {
+ super.onActive()
+ broadcastDispatcher.registerReceiver(receiver, filter, executor, UserHandle.ALL)
+ executor.execute {
+ postValue(getter())
+ }
+ }
+
+ override fun onInactive() {
+ super.onInactive()
+ broadcastDispatcher.unregisterReceiver(receiver)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 73532632c875..f19c49cc123f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -55,6 +55,8 @@ import android.util.Log;
import android.util.Slog;
import android.view.accessibility.AccessibilityManager;
+import androidx.lifecycle.Observer;
+
import com.android.internal.annotations.GuardedBy;
import com.android.settingslib.volume.MediaSessions;
import com.android.systemui.Dumpable;
@@ -64,6 +66,8 @@ import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.util.RingerModeLiveData;
+import com.android.systemui.util.RingerModeTracker;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -122,6 +126,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
private final NotificationManager mNoMan;
private final SettingObserver mObserver;
private final Receiver mReceiver = new Receiver();
+ private final RingerModeObservers mRingerModeObservers;
private final MediaSessions mMediaSessions;
protected C mCallbacks = new C();
private final State mState = new State();
@@ -145,7 +150,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
@Inject
public VolumeDialogControllerImpl(Context context, BroadcastDispatcher broadcastDispatcher,
- Optional<Lazy<StatusBar>> statusBarOptionalLazy) {
+ Optional<Lazy<StatusBar>> statusBarOptionalLazy, RingerModeTracker ringerModeTracker) {
mContext = context.getApplicationContext();
// TODO(b/150663459): remove this TV workaround once StatusBar is "unbound" on TVs
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
@@ -164,6 +169,11 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
mAudio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mNoMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mObserver = new SettingObserver(mWorker);
+ mRingerModeObservers = new RingerModeObservers(
+ (RingerModeLiveData) ringerModeTracker.getRingerMode(),
+ (RingerModeLiveData) ringerModeTracker.getRingerModeInternal()
+ );
+ mRingerModeObservers.init();
mBroadcastDispatcher = broadcastDispatcher;
mObserver.init();
mReceiver.init();
@@ -246,6 +256,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
mMediaSessions.destroy();
mObserver.destroy();
mReceiver.destroy();
+ mRingerModeObservers.destroy();
mWorkerThread.quitSafely();
}
@@ -528,7 +539,8 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
ss.name = STREAMS.get(stream);
checkRoutedToBluetoothW(stream);
}
- updateRingerModeExternalW(mAudio.getRingerMode());
+ // We are not destroyed so this is listening and has updated information
+ updateRingerModeExternalW(mRingerModeObservers.mRingerMode.getValue());
updateZenModeW();
updateZenConfig();
updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
@@ -575,7 +587,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
Events.writeEvent(Events.EVENT_MUTE_CHANGED, stream, muted);
}
if (muted && isRinger(stream)) {
- updateRingerModeInternalW(mAudio.getRingerModeInternal());
+ updateRingerModeInternalW(mRingerModeObservers.mRingerModeInternal.getValue());
}
return true;
}
@@ -964,6 +976,79 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
}
}
+ private final class RingerModeObservers {
+
+ private final RingerModeLiveData mRingerMode;
+ private final RingerModeLiveData mRingerModeInternal;
+
+ private final Observer<Integer> mRingerModeObserver = new Observer<Integer>() {
+ @Override
+ public void onChanged(Integer value) {
+ mWorker.post(() -> {
+ final int rm = value;
+ if (mRingerMode.getInitialSticky()) {
+ mState.ringerModeExternal = rm;
+ }
+ if (D.BUG) {
+ Log.d(TAG, "onChange ringer_mode rm="
+ + Util.ringerModeToString(rm));
+ }
+ if (updateRingerModeExternalW(rm)) {
+ mCallbacks.onStateChanged(mState);
+ }
+ }
+ );
+ }
+ };
+
+ private final Observer<Integer> mRingerModeInternalObserver = new Observer<Integer>() {
+ @Override
+ public void onChanged(Integer value) {
+ mWorker.post(() -> {
+ final int rm = value;
+ if (mRingerModeInternal.getInitialSticky()) {
+ mState.ringerModeInternal = rm;
+ }
+ if (D.BUG) {
+ Log.d(TAG, "onChange internal_ringer_mode rm="
+ + Util.ringerModeToString(rm));
+ }
+ if (updateRingerModeInternalW(rm)) {
+ mCallbacks.onStateChanged(mState);
+ }
+ }
+ );
+ }
+ };
+
+ RingerModeObservers(RingerModeLiveData ringerMode,
+ RingerModeLiveData ringerModeInternal) {
+ mRingerMode = ringerMode;
+ mRingerModeInternal = ringerModeInternal;
+ }
+
+ public void init() {
+ int initialValue = mRingerMode.getValue();
+ if (initialValue != -1) {
+ // If it's not -1, set it to the initial value, if it's -1, it means that the
+ // tracker is not listening already and will obtain the sticky value.
+ mState.ringerModeExternal = initialValue;
+ }
+ mRingerMode.observeForever(mRingerModeObserver);
+ initialValue = mRingerModeInternal.getValue();
+ if (initialValue != -1) {
+ // If it's not -1, set it to the initial value, if it's -1, it means that the
+ // tracker is not listening already and will obtain the sticky value.
+ mState.ringerModeInternal = initialValue;
+ }
+ mRingerModeInternal.observeForever(mRingerModeInternalObserver);
+ }
+
+ public void destroy() {
+ mRingerMode.removeObserver(mRingerModeObserver);
+ mRingerModeInternal.removeObserver(mRingerModeInternalObserver);
+ }
+ }
private final class SettingObserver extends ContentObserver {
private final Uri ZEN_MODE_URI =
@@ -1006,8 +1091,6 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
final IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
- filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
- filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
@@ -1042,18 +1125,6 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
+ stream + " devices=" + devices + " oldDevices=" + oldDevices);
changed = checkRoutedToBluetoothW(stream);
changed |= onVolumeChangedW(stream, 0);
- } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
- final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
- if (isInitialStickyBroadcast()) mState.ringerModeExternal = rm;
- if (D.BUG) Log.d(TAG, "onReceive RINGER_MODE_CHANGED_ACTION rm="
- + Util.ringerModeToString(rm));
- changed = updateRingerModeExternalW(rm);
- } else if (action.equals(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) {
- final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
- if (isInitialStickyBroadcast()) mState.ringerModeInternal = rm;
- if (D.BUG) Log.d(TAG, "onReceive INTERNAL_RINGER_MODE_CHANGED_ACTION rm="
- + Util.ringerModeToString(rm));
- changed = updateRingerModeInternalW(rm);
} else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
final boolean muted = intent
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index d47fceea9724..64590fd3a36b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -25,6 +25,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -36,6 +37,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
@UiThreadTest
@Test
public void showSecurityScreen_canInflateAllModes() {
+ mDependency.injectMockDependency(KeyguardStateController.class);
KeyguardSecurityContainer keyguardSecurityContainer =
new KeyguardSecurityContainer(getContext());
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 73f9d8ad6953..7403a11fecbf 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -29,6 +29,8 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -50,6 +52,7 @@ import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
+import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IRemoteCallback;
@@ -63,18 +66,24 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.Observer;
+
import com.android.internal.telephony.TelephonyIntents;
import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.util.RingerModeTracker;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -125,6 +134,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private BroadcastDispatcher mBroadcastDispatcher;
@Mock
private Executor mBackgroundExecutor;
+ @Mock
+ private RingerModeTracker mRingerModeTracker;
+ @Mock
+ private LiveData<Integer> mRingerModeLiveData;
private TestableLooper mTestableLooper;
private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -156,6 +169,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
context.addMockSystemService(DevicePolicyManager.class, mDevicePolicyManager);
context.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
+ when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
+
mTestableLooper = TestableLooper.get(this);
allowTestableLooperAsMainThread();
mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(context);
@@ -613,6 +628,29 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(mKeyguardUpdateMonitor.getSecondaryLockscreenRequirement(user)).isNull();
}
+ @Test
+ public void testRingerModeChange() {
+ ArgumentCaptor<Observer<Integer>> captor = ArgumentCaptor.forClass(Observer.class);
+ verify(mRingerModeLiveData).observeForever(captor.capture());
+ Observer<Integer> observer = captor.getValue();
+
+ KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+
+ mKeyguardUpdateMonitor.registerCallback(callback);
+
+ observer.onChanged(AudioManager.RINGER_MODE_NORMAL);
+ observer.onChanged(AudioManager.RINGER_MODE_SILENT);
+ observer.onChanged(AudioManager.RINGER_MODE_VIBRATE);
+
+ mTestableLooper.processAllMessages();
+
+ InOrder orderVerify = inOrder(callback);
+ orderVerify.verify(callback).onRingerModeChanged(anyInt()); // Initial update on register
+ orderVerify.verify(callback).onRingerModeChanged(AudioManager.RINGER_MODE_NORMAL);
+ orderVerify.verify(callback).onRingerModeChanged(AudioManager.RINGER_MODE_SILENT);
+ orderVerify.verify(callback).onRingerModeChanged(AudioManager.RINGER_MODE_VIBRATE);
+ }
+
private void setBroadcastReceiverPendingResult(BroadcastReceiver receiver) {
BroadcastReceiver.PendingResult pendingResult =
new BroadcastReceiver.PendingResult(Activity.RESULT_OK,
@@ -643,7 +681,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
protected TestableKeyguardUpdateMonitor(Context context) {
super(context,
TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(),
- mBroadcastDispatcher, mDumpManager, mBackgroundExecutor);
+ mBroadcastDispatcher, mDumpManager,
+ mRingerModeTracker, mBackgroundExecutor);
mStrongAuthTracker = KeyguardUpdateMonitorTest.this.mStrongAuthTracker;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 32604f8609fa..b2c35867e789 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -38,6 +38,8 @@ import com.android.systemui.broadcast.FakeBroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import org.junit.After;
import org.junit.Before;
@@ -97,6 +99,12 @@ public abstract class SysuiTestCase {
// A lot of tests get the LocalBluetoothManager, often via several layers of indirection.
// None of them actually need it.
mDependency.injectMockDependency(LocalBluetoothManager.class);
+
+ // Notifications tests are injecting one of these, causing many classes (including
+ // KeyguardUpdateMonitor to be created (injected).
+ // TODO(b/1531701009) Clean up NotificationContentView creation to prevent this
+ mDependency.injectMockDependency(SmartReplyController.class);
+ mDependency.injectMockDependency(NotificationBlockingHelperManager.class);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
index 137a126f539d..300cb212ffb1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.globalactions;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
@@ -52,6 +53,8 @@ import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.RingerModeLiveData;
+import com.android.systemui.util.RingerModeTracker;
import org.junit.Before;
import org.junit.Test;
@@ -95,6 +98,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
@Mock private ControlsListingController mControlsListingController;
@Mock private ControlsController mControlsController;
@Mock private UiEventLogger mUiEventLogger;
+ @Mock private RingerModeTracker mRingerModeTracker;
+ @Mock private RingerModeLiveData mRingerModeLiveData;
private TestableLooper mTestableLooper;
@@ -103,6 +108,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
allowTestableLooperAsMainThread();
+
+ when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
mGlobalActionsDialog = new GlobalActionsDialog(mContext,
mWindowManagerFuncs,
mAudioManager,
@@ -133,7 +140,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
mBackgroundExecutor,
mControlsListingController,
mControlsController,
- mUiEventLogger
+ mUiEventLogger,
+ mRingerModeTracker
);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
new file mode 100644
index 000000000000..2489c301f6f5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 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.systemui.util
+
+import android.content.BroadcastReceiver
+import android.content.IntentFilter
+import android.os.UserHandle
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.lifecycle.Observer
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.BroadcastDispatcher
+import org.junit.After
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations
+import java.util.concurrent.Executor
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class RingerModeLiveDataTest : SysuiTestCase() {
+
+ companion object {
+ private fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+ private fun <T> any(): T = Mockito.any()
+ private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
+ private val INTENT = "INTENT"
+ }
+
+ @Mock
+ private lateinit var broadcastDispatcher: BroadcastDispatcher
+ @Mock
+ private lateinit var valueSupplier: () -> Int
+ @Mock
+ private lateinit var observer: Observer<Int>
+ @Captor
+ private lateinit var broadcastReceiverCaptor: ArgumentCaptor<BroadcastReceiver>
+ @Captor
+ private lateinit var intentFilterCaptor: ArgumentCaptor<IntentFilter>
+
+ // Run everything immediately
+ private val executor = Executor { it.run() }
+ private lateinit var liveData: RingerModeLiveData
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ liveData = RingerModeLiveData(broadcastDispatcher, executor, INTENT, valueSupplier)
+ }
+
+ @After
+ fun tearDown() {
+ liveData.removeObserver(observer)
+ }
+
+ @Test
+ fun testInit_broadcastNotRegistered() {
+ verifyNoMoreInteractions(broadcastDispatcher)
+ }
+
+ @Test
+ fun testOnActive_broadcastRegistered() {
+ liveData.observeForever(observer)
+ verify(broadcastDispatcher).registerReceiver(any(), any(), eq(executor), eq(UserHandle.ALL))
+ }
+
+ @Test
+ fun testOnActive_intentFilterHasIntent() {
+ liveData.observeForever(observer)
+ verify(broadcastDispatcher).registerReceiver(any(), capture(intentFilterCaptor), any(),
+ any())
+ assertTrue(intentFilterCaptor.value.hasAction(INTENT))
+ }
+
+ @Test
+ fun testOnActive_valueObtained() {
+ liveData.observeForever(observer)
+ verify(valueSupplier).invoke()
+ }
+
+ @Test
+ fun testOnInactive_broadcastUnregistered() {
+ liveData.observeForever(observer)
+ liveData.removeObserver(observer)
+ verify(broadcastDispatcher).unregisterReceiver(any())
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
index 8cc83dd99b53..6166cd76e005 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
@@ -31,6 +31,7 @@ import android.media.session.MediaSession;
import android.os.Handler;
import android.os.Process;
import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
@@ -38,7 +39,10 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.util.RingerModeLiveData;
+import com.android.systemui.util.RingerModeTracker;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,6 +53,7 @@ import java.util.Optional;
@RunWith(AndroidTestingRunner.class)
@SmallTest
+@TestableLooper.RunWithLooper
public class VolumeDialogControllerImplTest extends SysuiTestCase {
TestableVolumeDialogControllerImpl mVolumeController;
@@ -56,18 +61,35 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
StatusBar mStatusBar;
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ private RingerModeTracker mRingerModeTracker;
+ @Mock
+ private RingerModeLiveData mRingerModeLiveData;
+ @Mock
+ private RingerModeLiveData mRingerModeInternalLiveData;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
+ when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
+ when(mRingerModeTracker.getRingerModeInternal()).thenReturn(mRingerModeInternalLiveData);
+ // Initial non-set value
+ when(mRingerModeLiveData.getValue()).thenReturn(-1);
+ when(mRingerModeInternalLiveData.getValue()).thenReturn(-1);
+
mCallback = mock(VolumeDialogControllerImpl.C.class);
mStatusBar = mock(StatusBar.class);
mVolumeController = new TestableVolumeDialogControllerImpl(mContext, mCallback, mStatusBar,
- mBroadcastDispatcher);
+ mBroadcastDispatcher, mRingerModeTracker);
mVolumeController.setEnableDialogs(true, true);
}
+ @After
+ public void tearDown() {
+ mVolumeController.destroy();
+ }
+
@Test
public void testRegisteredWithDispatcher() {
verify(mBroadcastDispatcher).registerReceiverWithHandler(any(BroadcastReceiver.class),
@@ -109,7 +131,7 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
TestableVolumeDialogControllerImpl
nullStatusBarTestableDialog =
new TestableVolumeDialogControllerImpl(
- mContext, callback, null, mBroadcastDispatcher);
+ mContext, callback, null, mBroadcastDispatcher, mRingerModeTracker);
nullStatusBarTestableDialog.setEnableDialogs(true, true);
nullStatusBarTestableDialog.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
verify(callback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
@@ -127,12 +149,26 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase {
mVolumeController.mMediaSessionsCallbacksW.onRemoteRemoved(token);
}
+ @Test
+ public void testRingerModeLiveDataObserving() {
+ verify(mRingerModeLiveData).observeForever(any());
+ verify(mRingerModeInternalLiveData).observeForever(any());
+ }
+
+ @Test
+ public void testRingerModeOnDestroy_observersRemoved() {
+ mVolumeController.destroy();
+
+ verify(mRingerModeLiveData).removeObserver(any());
+ verify(mRingerModeInternalLiveData).removeObserver(any());
+ }
+
static class TestableVolumeDialogControllerImpl extends VolumeDialogControllerImpl {
TestableVolumeDialogControllerImpl(Context context, C callback, StatusBar s,
- BroadcastDispatcher broadcastDispatcher) {
+ BroadcastDispatcher broadcastDispatcher, RingerModeTracker ringerModeTracker) {
super(
context, broadcastDispatcher,
- s == null ? Optional.empty() : Optional.of(() -> s));
+ s == null ? Optional.empty() : Optional.of(() -> s), ringerModeTracker);
mCallbacks = callback;
}
}