Fix BroadcastReceiver registration in DefaultDeviceEffectsApplier
Test: atest DefaultDeviceEffectsApplierTest
Bug: 308673343
Change-Id: I0dc733b4846876af4c27737ef6285d8e4ab4597e
diff --git a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
index 82faeef..8855666 100644
--- a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
+++ b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
@@ -32,6 +32,8 @@
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ConfigChangeOrigin;
+import com.android.internal.annotations.GuardedBy;
+
/** Default implementation for {@link DeviceEffectsApplier}. */
class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
@@ -50,6 +52,10 @@
private final UiModeManager mUiModeManager;
private final WallpaperManager mWallpaperManager;
+ private final Object mRegisterReceiverLock = new Object();
+ @GuardedBy("mRegisterReceiverLock")
+ private boolean mIsScreenOffReceiverRegistered;
+
private ZenDeviceEffects mLastAppliedEffects = new ZenDeviceEffects.Builder().build();
private boolean mPendingNightMode;
@@ -96,7 +102,6 @@
private void updateOrScheduleNightMode(boolean useNightMode, @ConfigChangeOrigin int origin) {
mPendingNightMode = useNightMode;
- safeUnregisterReceiver(mNightModeWhenScreenOff);
// Changing the theme can be disruptive for the user (Activities are likely recreated, may
// lose some state). Therefore we only apply the change immediately if the rule was
@@ -106,17 +111,18 @@
|| origin == ZenModeConfig.UPDATE_ORIGIN_USER
|| origin == ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
|| !mPowerManager.isInteractive()) {
+ unregisterScreenOffReceiver();
updateNightModeImmediately(useNightMode);
} else {
- mContext.registerReceiver(mNightModeWhenScreenOff, SCREEN_OFF_INTENT_FILTER,
- Context.RECEIVER_NOT_EXPORTED);
+ registerScreenOffReceiver();
}
}
+ @GuardedBy("mRegisterReceiverLock")
private final BroadcastReceiver mNightModeWhenScreenOff = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- safeUnregisterReceiver(mNightModeWhenScreenOff);
+ unregisterScreenOffReceiver();
updateNightModeImmediately(mPendingNightMode);
}
};
@@ -130,11 +136,22 @@
});
}
- private void safeUnregisterReceiver(BroadcastReceiver br) {
- try {
- mContext.unregisterReceiver(br);
- } catch (IllegalArgumentException e) {
- // It's fine, we haven't registered it yet.
+ private void registerScreenOffReceiver() {
+ synchronized (mRegisterReceiverLock) {
+ if (!mIsScreenOffReceiverRegistered) {
+ mContext.registerReceiver(mNightModeWhenScreenOff, SCREEN_OFF_INTENT_FILTER,
+ Context.RECEIVER_NOT_EXPORTED);
+ mIsScreenOffReceiverRegistered = true;
+ }
+ }
+ }
+
+ private void unregisterScreenOffReceiver() {
+ synchronized (mRegisterReceiverLock) {
+ if (mIsScreenOffReceiverRegistered) {
+ mIsScreenOffReceiverRegistered = false;
+ mContext.unregisterReceiver(mNightModeWhenScreenOff);
+ }
}
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
index c9e6d6a..8936dc6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
@@ -27,7 +27,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -200,7 +199,7 @@
// So the effect is applied, and we stopped listening for this event.
verify(mUiModeManager).setNightModeActivatedForCustomMode(
eq(MODE_NIGHT_CUSTOM_TYPE_BEDTIME), eq(true));
- verify(mContext, atLeastOnce()).unregisterReceiver(eq(screenOffReceiver));
+ verify(mContext).unregisterReceiver(eq(screenOffReceiver));
}
@Test