Merge "Fix NPE with registering content listener"

This commit is contained in:
Derek Jedral
2023-02-01 00:24:00 +00:00
committed by Android (Google) Code Review
3 changed files with 44 additions and 13 deletions

View File

@@ -87,10 +87,10 @@ public class ActiveUnlockContentListener {
} }
/** Starts listening for updates from the ContentProvider, and fetches the current value. */ /** Returns true if start listening for updates from the ContentProvider, false otherwise. */
public synchronized void subscribe() { public synchronized boolean subscribe() {
if (mSubscribed && mUri != null) { if (mSubscribed || mUri == null) {
return; return false;
} }
mSubscribed = true; mSubscribed = true;
mContext.getContentResolver().registerContentObserver( mContext.getContentResolver().registerContentObserver(
@@ -99,15 +99,17 @@ public class ActiveUnlockContentListener {
() -> { () -> {
getContentFromUri(); getContentFromUri();
}); });
return true;
} }
/** Stops listening for updates from the ContentProvider. */ /** Returns true if stops listening for updates from the ContentProvider, false otherewise. */
public synchronized void unsubscribe() { public synchronized boolean unsubscribe() {
if (!mSubscribed && mUri != null) { if (!mSubscribed || mUri == null) {
return; return false;
} }
mSubscribed = false; mSubscribed = false;
mContext.getContentResolver().unregisterContentObserver(mContentObserver); mContext.getContentResolver().unregisterContentObserver(mContentObserver);
return true;
} }
/** Retrieves the most recently fetched value from the ContentProvider. */ /** Retrieves the most recently fetched value from the ContentProvider. */

View File

@@ -50,6 +50,7 @@ public class ActiveUnlockStatusPreferenceController
private final CombinedBiometricStatusUtils mCombinedBiometricStatusUtils; private final CombinedBiometricStatusUtils mCombinedBiometricStatusUtils;
private final ActiveUnlockSummaryListener mActiveUnlockSummaryListener; private final ActiveUnlockSummaryListener mActiveUnlockSummaryListener;
private final ActiveUnlockDeviceNameListener mActiveUnlockDeviceNameListener; private final ActiveUnlockDeviceNameListener mActiveUnlockDeviceNameListener;
private final boolean mIsAvailable;
public ActiveUnlockStatusPreferenceController(@NonNull Context context) { public ActiveUnlockStatusPreferenceController(@NonNull Context context) {
this(context, KEY_ACTIVE_UNLOCK_SETTINGS); this(context, KEY_ACTIVE_UNLOCK_SETTINGS);
@@ -59,6 +60,7 @@ public class ActiveUnlockStatusPreferenceController
@NonNull Context context, @NonNull String key) { @NonNull Context context, @NonNull String key) {
super(context, key); super(context, key);
mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(context); mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(context);
mIsAvailable = mActiveUnlockStatusUtils.isAvailable();
mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(context, getUserId()); mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(context, getUserId());
OnContentChangedListener onSummaryChangedListener = new OnContentChangedListener() { OnContentChangedListener onSummaryChangedListener = new OnContentChangedListener() {
@Override @Override
@@ -90,8 +92,10 @@ public class ActiveUnlockStatusPreferenceController
/** Subscribes to update preference summary dynamically. */ /** Subscribes to update preference summary dynamically. */
@OnLifecycleEvent(Lifecycle.Event.ON_START) @OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() { public void onStart() {
mActiveUnlockSummaryListener.subscribe(); if (mIsAvailable) {
mActiveUnlockDeviceNameListener.subscribe(); mActiveUnlockSummaryListener.subscribe();
mActiveUnlockDeviceNameListener.subscribe();
}
} }
/** Resets the preference reference on resume. */ /** Resets the preference reference on resume. */
@@ -105,8 +109,10 @@ public class ActiveUnlockStatusPreferenceController
/** Unsubscribes to prevent leaked listener. */ /** Unsubscribes to prevent leaked listener. */
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() { public void onStop() {
mActiveUnlockSummaryListener.unsubscribe(); if (mIsAvailable) {
mActiveUnlockDeviceNameListener.unsubscribe(); mActiveUnlockSummaryListener.unsubscribe();
mActiveUnlockDeviceNameListener.unsubscribe();
}
} }
@Override @Override
@@ -127,7 +133,7 @@ public class ActiveUnlockStatusPreferenceController
// This should never be called, as getAvailabilityStatus() will return the exact value. // This should never be called, as getAvailabilityStatus() will return the exact value.
// However, this is an abstract method in BiometricStatusPreferenceController, and so // However, this is an abstract method in BiometricStatusPreferenceController, and so
// needs to be overridden. // needs to be overridden.
return mActiveUnlockStatusUtils.isAvailable(); return mIsAvailable;
} }
@Override @Override

View File

@@ -18,6 +18,7 @@ package com.android.settings.biometrics.activeunlock;
import static com.google.common.truth.Truth.assertThat; 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.spy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.robolectric.shadows.ShadowLooper.idleMainLooper; import static org.robolectric.shadows.ShadowLooper.idleMainLooper;
@@ -43,6 +44,8 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import java.util.ArrayList;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDeviceConfig.class}) @Config(shadows = {ShadowDeviceConfig.class})
public class ActiveUnlockContentListenerTest { public class ActiveUnlockContentListenerTest {
@@ -136,6 +139,26 @@ public class ActiveUnlockContentListenerTest {
assertThat(mUpdateCount).isEqualTo(1); 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) { private void updateContent(String content) {
FakeContentProvider.setTileSummary(content); FakeContentProvider.setTileSummary(content);
mContext.getContentResolver().notifyChange( mContext.getContentResolver().notifyChange(