diff --git a/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListener.java b/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListener.java index c2a8f39b54b..8cc7d6af331 100644 --- a/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListener.java +++ b/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListener.java @@ -87,10 +87,10 @@ public class ActiveUnlockContentListener { } - /** Starts listening for updates from the ContentProvider, and fetches the current value. */ - public synchronized void subscribe() { - if (mSubscribed && mUri != null) { - return; + /** Returns true if start listening for updates from the ContentProvider, false otherwise. */ + public synchronized boolean subscribe() { + if (mSubscribed || mUri == null) { + return false; } mSubscribed = true; mContext.getContentResolver().registerContentObserver( @@ -99,15 +99,17 @@ public class ActiveUnlockContentListener { () -> { getContentFromUri(); }); + return true; } - /** Stops listening for updates from the ContentProvider. */ - public synchronized void unsubscribe() { - if (!mSubscribed && mUri != null) { - return; + /** Returns true if stops listening for updates from the ContentProvider, false otherewise. */ + public synchronized boolean unsubscribe() { + if (!mSubscribed || mUri == null) { + return false; } mSubscribed = false; mContext.getContentResolver().unregisterContentObserver(mContentObserver); + return true; } /** Retrieves the most recently fetched value from the ContentProvider. */ diff --git a/src/com/android/settings/biometrics/activeunlock/ActiveUnlockStatusPreferenceController.java b/src/com/android/settings/biometrics/activeunlock/ActiveUnlockStatusPreferenceController.java index 31c72aee722..ff835f80ce0 100644 --- a/src/com/android/settings/biometrics/activeunlock/ActiveUnlockStatusPreferenceController.java +++ b/src/com/android/settings/biometrics/activeunlock/ActiveUnlockStatusPreferenceController.java @@ -50,6 +50,7 @@ public class ActiveUnlockStatusPreferenceController private final CombinedBiometricStatusUtils mCombinedBiometricStatusUtils; private final ActiveUnlockSummaryListener mActiveUnlockSummaryListener; private final ActiveUnlockDeviceNameListener mActiveUnlockDeviceNameListener; + private final boolean mIsAvailable; public ActiveUnlockStatusPreferenceController(@NonNull Context context) { this(context, KEY_ACTIVE_UNLOCK_SETTINGS); @@ -59,6 +60,7 @@ public class ActiveUnlockStatusPreferenceController @NonNull Context context, @NonNull String key) { super(context, key); mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(context); + mIsAvailable = mActiveUnlockStatusUtils.isAvailable(); mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(context, getUserId()); OnContentChangedListener onSummaryChangedListener = new OnContentChangedListener() { @Override @@ -90,8 +92,10 @@ public class ActiveUnlockStatusPreferenceController /** Subscribes to update preference summary dynamically. */ @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { - mActiveUnlockSummaryListener.subscribe(); - mActiveUnlockDeviceNameListener.subscribe(); + if (mIsAvailable) { + mActiveUnlockSummaryListener.subscribe(); + mActiveUnlockDeviceNameListener.subscribe(); + } } /** Resets the preference reference on resume. */ @@ -105,8 +109,10 @@ public class ActiveUnlockStatusPreferenceController /** Unsubscribes to prevent leaked listener. */ @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onStop() { - mActiveUnlockSummaryListener.unsubscribe(); - mActiveUnlockDeviceNameListener.unsubscribe(); + if (mIsAvailable) { + mActiveUnlockSummaryListener.unsubscribe(); + mActiveUnlockDeviceNameListener.unsubscribe(); + } } @Override @@ -127,7 +133,7 @@ public class ActiveUnlockStatusPreferenceController // This should never be called, as getAvailabilityStatus() will return the exact value. // However, this is an abstract method in BiometricStatusPreferenceController, and so // needs to be overridden. - return mActiveUnlockStatusUtils.isAvailable(); + return mIsAvailable; } @Override diff --git a/tests/robotests/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListenerTest.java b/tests/robotests/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListenerTest.java index cb0c9420e80..4da815131e0 100644 --- a/tests/robotests/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListenerTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListenerTest.java @@ -18,6 +18,7 @@ package com.android.settings.biometrics.activeunlock; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import static org.robolectric.shadows.ShadowLooper.idleMainLooper; @@ -43,6 +44,8 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import java.util.ArrayList; + @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowDeviceConfig.class}) public class ActiveUnlockContentListenerTest { @@ -136,6 +139,26 @@ public class ActiveUnlockContentListenerTest { assertThat(mUpdateCount).isEqualTo(1); } + @Test + public void noProvider_subscribeDoesntRegisterObserver() { + when(mPackageManager.getInstalledPackages(any())) + .thenReturn(new ArrayList<>()); + OnContentChangedListener listener = new OnContentChangedListener() { + @Override + public void onContentChanged(String newValue) {} + }; + + ActiveUnlockContentListener contentListener = + new ActiveUnlockContentListener( + mContext, + listener, + "logTag", + FakeContentProvider.METHOD_SUMMARY, + FakeContentProvider.KEY_SUMMARY); + + assertThat(contentListener.subscribe()).isFalse(); + } + private void updateContent(String content) { FakeContentProvider.setTileSummary(content); mContext.getContentResolver().notifyChange(