Merge "Disable the defulat animation of the RecyclerView to avoid UI jank." into rvc-dev
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index a493ae0..04df11a 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -95,9 +95,20 @@
private final FaceSettingsEnrollButtonPreferenceController.Listener mEnrollListener = intent ->
startActivityForResult(intent, ENROLL_REQUEST);
- public static boolean isAvailable(Context context) {
+ /**
+ * @param context
+ * @return true if the Face hardware is detected.
+ */
+ public static boolean isFaceHardwareDetected(Context context) {
FaceManager manager = Utils.getFaceManagerOrNull(context);
- return manager != null && manager.isHardwareDetected();
+ boolean isHardwareDetected = false;
+ if (manager == null) {
+ Log.d(TAG, "FaceManager is null");
+ } else {
+ isHardwareDetected = manager.isHardwareDetected();
+ Log.d(TAG, "FaceManager is not null. Hardware detected: " + isHardwareDetected);
+ }
+ return manager != null && isHardwareDetected;
}
@Override
@@ -126,7 +137,7 @@
super.onCreate(savedInstanceState);
final Context context = getPrefContext();
- if (!isAvailable(context)) {
+ if (!isFaceHardwareDetected(context)) {
Log.w(TAG, "no faceManager, finish this");
finish();
return;
@@ -273,7 +284,7 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- if (!isAvailable(context)) {
+ if (!isFaceHardwareDetected(context)) {
return null;
}
mControllers = buildPreferenceControllers(context, getSettingsLifecycle());
@@ -314,7 +325,7 @@
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
- if (isAvailable(context)) {
+ if (isFaceHardwareDetected(context)) {
return buildPreferenceControllers(context, null /* lifecycle */);
} else {
return null;
@@ -323,7 +334,7 @@
@Override
protected boolean isPageSearchEnabled(Context context) {
- if (isAvailable(context)) {
+ if (isFaceHardwareDetected(context)) {
return hasEnrolledBiometrics(context);
}
@@ -333,7 +344,10 @@
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
- if (isAvailable(context)) {
+ final boolean isFaceHardwareDetected = isFaceHardwareDetected(context);
+ Log.d(TAG, "Get non indexable keys. isFaceHardwareDetected: "
+ + isFaceHardwareDetected + ", size:" + keys.size());
+ if (isFaceHardwareDetected) {
final boolean hasEnrolled = hasEnrolledBiometrics(context);
keys.add(hasEnrolled ? PREF_KEY_ENROLL_FACE_UNLOCK
: PREF_KEY_DELETE_FACE_DATA);
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
index a54171e..bde146b 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
@@ -22,10 +22,10 @@
import android.hardware.face.FaceManager;
import android.provider.Settings;
-import com.android.settings.Utils;
-
import androidx.preference.Preference;
+import com.android.settings.Utils;
+
/**
* Preference controller for Face settings page controlling the ability to use
* Face authentication in apps (through BiometricPrompt).
@@ -51,7 +51,7 @@
@Override
public boolean isChecked() {
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
return false;
}
return Settings.Secure.getIntForUser(
@@ -67,7 +67,7 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
preference.setEnabled(false);
} else if (!mFaceManager.hasEnrolledTemplates(getUserId())) {
preference.setEnabled(false);
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
index e5fee75..200c0b9 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
@@ -93,7 +93,7 @@
@Override
public boolean isChecked() {
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
return true;
}
// Set to disabled until we know the true value.
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java
index c65cd23..c515742 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java
@@ -25,7 +25,6 @@
import androidx.preference.Preference;
import com.android.settings.Utils;
-import com.android.settings.core.TogglePreferenceController;
/**
* Preference controller giving the user an option to always require confirmation.
@@ -65,7 +64,7 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
preference.setEnabled(false);
} else if (!mFaceManager.hasEnrolledTemplates(getUserId())) {
preference.setEnabled(false);
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
index 7e7a748..8ee7ffd 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
@@ -53,7 +53,7 @@
@Override
public boolean isChecked() {
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
return false;
} else if (getRestrictingAdmin() != null) {
return false;
@@ -77,7 +77,7 @@
public void updateState(Preference preference) {
EnforcedAdmin admin;
super.updateState(preference);
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
preference.setEnabled(false);
} else if ((admin = getRestrictingAdmin()) != null) {
((RestrictedSwitchPreference) preference).setDisabledByAdmin(admin);
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
index 5c46a3d..0a2757b 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
@@ -47,7 +47,7 @@
@Override
public boolean isChecked() {
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
return false;
} else if (getRestrictingAdmin() != null) {
return false;
@@ -69,7 +69,7 @@
public void updateState(Preference preference) {
EnforcedAdmin admin;
super.updateState(preference);
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
preference.setEnabled(false);
} else if ((admin = getRestrictingAdmin()) != null) {
((RestrictedSwitchPreference) preference).setDisabledByAdmin(admin);
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
index a4da759..6c98060 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
@@ -165,7 +165,7 @@
.findViewById(R.id.security_settings_face_settings_remove_button);
mButton.setOnClickListener(this);
- if (!FaceSettings.isAvailable(mContext)) {
+ if (!FaceSettings.isFaceHardwareDetected(mContext)) {
mButton.setEnabled(false);
} else {
mButton.setEnabled(!mRemoving);
diff --git a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
index cb82b5e..648da9b 100644
--- a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
@@ -41,7 +41,7 @@
@Override
protected boolean isDeviceSupported() {
- return mFaceManager != null && mFaceManager.isHardwareDetected();
+ return FaceSettings.isFaceHardwareDetected(mContext);
}
@Override
diff --git a/src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java b/src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
index 8e7031d..49a9de6 100644
--- a/src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
+++ b/src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.provider.Settings;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -31,6 +32,7 @@
public class AssistGestureSettingsPreferenceController extends GesturePreferenceController {
+ private static final String TAG = "AssistGesture";
private static final String PREF_KEY_VIDEO = "gesture_assist_video";
private static final String SECURE_KEY_ASSIST = ASSIST_GESTURE_ENABLED;
@@ -55,8 +57,11 @@
@Override
public int getAvailabilityStatus() {
- final boolean isAvailable = mAssistOnly ? mFeatureProvider.isSupported(mContext)
- : mFeatureProvider.isSensorAvailable(mContext);
+ final boolean isSupported = mFeatureProvider.isSupported(mContext);
+ final boolean isSensorAvailable = mFeatureProvider.isSensorAvailable(mContext);
+ final boolean isAvailable = mAssistOnly ? isSupported : isSensorAvailable;
+ Log.d(TAG, "mAssistOnly:" + mAssistOnly + ", isSupported:" + isSupported
+ + ", isSensorAvailable:" + isSensorAvailable);
return isAvailable ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 4d1a1d4..d30fe59 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -38,14 +38,14 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.AsyncLoaderCompat;
-import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>> {
@@ -56,7 +56,7 @@
static final int CARD_CONTENT_LOADER_ID = 1;
private static final String TAG = "ContextualCardLoader";
- private static final long ELIGIBILITY_CHECKER_TIMEOUT_MS = 300;
+ private static final long ELIGIBILITY_CHECKER_TIMEOUT_MS = 400;
private final ContentObserver mObserver = new ContentObserver(
new Handler(Looper.getMainLooper())) {
@@ -184,23 +184,37 @@
@VisibleForTesting
List<ContextualCard> filterEligibleCards(List<ContextualCard> candidates) {
+ final ExecutorService executor = Executors.newFixedThreadPool(candidates.size());
final List<ContextualCard> cards = new ArrayList<>();
- final List<Future<ContextualCard>> eligibleCards = new ArrayList<>();
+ List<Future<ContextualCard>> eligibleCards = new ArrayList<>();
- for (ContextualCard card : candidates) {
- final EligibleCardChecker checker = new EligibleCardChecker(mContext, card);
- eligibleCards.add(ThreadUtils.postOnBackgroundThread(checker));
+ final List<EligibleCardChecker> checkers = candidates.stream()
+ .map(card -> new EligibleCardChecker(mContext, card))
+ .collect(Collectors.toList());
+ try {
+ eligibleCards = executor.invokeAll(checkers, ELIGIBILITY_CHECKER_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.w(TAG, "Failed to get eligible states for all cards", e);
}
+ executor.shutdown();
+
// Collect future and eligible cards
- for (Future<ContextualCard> cardFuture : eligibleCards) {
+ for (int i = 0; i < eligibleCards.size(); i++) {
+ final Future<ContextualCard> cardFuture = eligibleCards.get(i);
+ if (cardFuture.isCancelled()) {
+ Log.w(TAG, "Timeout getting eligible state for card: "
+ + candidates.get(i).getSliceUri());
+ continue;
+ }
+
try {
- final ContextualCard card = cardFuture.get(ELIGIBILITY_CHECKER_TIMEOUT_MS,
- TimeUnit.MILLISECONDS);
+ final ContextualCard card = cardFuture.get();
if (card != null) {
cards.add(card);
}
- } catch (ExecutionException | InterruptedException | TimeoutException e) {
- Log.w(TAG, "Failed to get eligible state for card: " + e.toString());
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to get eligible state for card", e);
}
}
return cards;
diff --git a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
index 4340330..46b4c86 100644
--- a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
+++ b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
@@ -22,6 +22,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
+import android.os.AsyncTask;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -32,6 +33,7 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.utils.ThreadUtils;
import java.util.List;
import java.util.concurrent.Callable;
@@ -115,7 +117,12 @@
// Register a trivial callback to pin the slice
manager.registerSliceCallback(uri, callback);
final Slice slice = manager.bindSlice(uri);
- manager.unregisterSliceCallback(uri, callback);
+
+ // Workaround of unpinning slice in the same SerialExecutor of AsyncTask as SliceCallback's
+ // observer.
+ ThreadUtils.postOnMainThread(() ->
+ AsyncTask.execute(() -> manager.unregisterSliceCallback(uri, callback))
+ );
return slice;
}
diff --git a/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java b/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java
index 6067b77..19e25fc 100644
--- a/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java
+++ b/src/com/android/settings/security/trustagent/TrustAgentListPreferenceController.java
@@ -23,7 +23,6 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
-import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -46,6 +45,7 @@
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
import com.android.settingslib.search.SearchIndexableRaw;
+import java.util.ArrayList;
import java.util.List;
public class TrustAgentListPreferenceController extends AbstractPreferenceController
@@ -66,6 +66,9 @@
private Intent mTrustAgentClickIntent;
private PreferenceCategory mSecurityCategory;
+ @VisibleForTesting
+ final List<String> mTrustAgentsKeyList;
+
public TrustAgentListPreferenceController(Context context, SecuritySettings host,
Lifecycle lifecycle) {
super(context);
@@ -74,6 +77,7 @@
mHost = host;
mLockPatternUtils = provider.getLockPatternUtils(context);
mTrustAgentManager = provider.getTrustAgentManager();
+ mTrustAgentsKeyList = new ArrayList();
if (lifecycle != null) {
lifecycle.addObserver(this);
}
@@ -113,7 +117,7 @@
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
- if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ if (!mTrustAgentsKeyList.contains(preference.getKey())) {
return super.handlePreferenceTreeClick(preference);
}
final ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(
@@ -189,6 +193,7 @@
mSecurityCategory.removePreference(oldAgent);
}
}
+ mTrustAgentsKeyList.clear();
// Then add new ones.
final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID);
@@ -196,6 +201,7 @@
final RestrictedPreference trustAgentPreference =
new RestrictedPreference(mSecurityCategory.getContext());
TrustAgentManager.TrustAgentComponentInfo agent = agents.get(i);
+ mTrustAgentsKeyList.add(PREF_KEY_TRUST_AGENT + i);
trustAgentPreference.setKey(PREF_KEY_TRUST_AGENT + i);
trustAgentPreference.setTitle(agent.title);
trustAgentPreference.setSummary(agent.summary);
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 75061a5..c22d001 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -143,7 +143,7 @@
@VisibleForTesting
final Map<Uri, SliceBackgroundWorker> mPinnedWorkers = new ArrayMap<>();
- private boolean mNightMode;
+ private Boolean mNightMode;
public SettingsSliceProvider() {
super(READ_SEARCH_INDEXABLES);
@@ -153,8 +153,6 @@
public boolean onCreateSliceProvider() {
mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
mSliceWeakDataCache = new WeakHashMap<>();
- mNightMode = Utils.isNightMode(getContext());
- getContext().setTheme(R.style.Theme_SettingsBase);
return true;
}
@@ -207,7 +205,10 @@
}
final boolean nightMode = Utils.isNightMode(getContext());
- if (mNightMode != nightMode) {
+ if (mNightMode == null) {
+ mNightMode = nightMode;
+ getContext().setTheme(R.style.Theme_SettingsBase);
+ } else if (mNightMode != nightMode) {
Log.d(TAG, "Night mode changed, reload theme");
mNightMode = nightMode;
getContext().getTheme().rebase();
diff --git a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentListPreferenceControllerTest.java
index c0fbff7..0463e00 100644
--- a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentListPreferenceControllerTest.java
@@ -16,10 +16,8 @@
package com.android.settings.security.trustagent;
-import static com.android.settings.security.trustagent.TrustAgentListPreferenceController
- .PREF_KEY_SECURITY_CATEGORY;
-import static com.android.settings.security.trustagent.TrustAgentListPreferenceController
- .PREF_KEY_TRUST_AGENT;
+import static com.android.settings.security.trustagent.TrustAgentListPreferenceController.PREF_KEY_SECURITY_CATEGORY;
+import static com.android.settings.security.trustagent.TrustAgentListPreferenceController.PREF_KEY_TRUST_AGENT;
import static com.google.common.truth.Truth.assertThat;
@@ -173,6 +171,26 @@
}
@Test
+ public void onResume_controllerShouldHasKey() {
+ final List<TrustAgentManager.TrustAgentComponentInfo> agents = new ArrayList<>();
+ final TrustAgentManager.TrustAgentComponentInfo agent =
+ mock(TrustAgentManager.TrustAgentComponentInfo.class);
+ agent.title = "Test_title";
+ agent.summary = "test summary";
+ agent.componentName = new ComponentName("pkg", "agent");
+ agent.admin = null;
+ agents.add(agent);
+ when(mTrustAgentManager.getActiveTrustAgents(mActivity, mLockPatternUtils))
+ .thenReturn(agents);
+ final String key = PREF_KEY_TRUST_AGENT + 0;
+
+ mController.displayPreference(mScreen);
+ mController.onResume();
+
+ assertThat(mController.mTrustAgentsKeyList).containsExactly(key);
+ }
+
+ @Test
public void updateDynamicRawDataToIndex_shouldIndexAgents() {
final List<TrustAgentManager.TrustAgentComponentInfo> agents = new ArrayList<>();
final TrustAgentManager.TrustAgentComponentInfo agent =
@@ -190,5 +208,4 @@
assertThat(indexRaws).hasSize(1);
}
-
}