Snap for 6618402 from 964bb4959a to mainline-release

Change-Id: I7c2f1ed9af4813d43b103e581df1b56f754694d8
This commit is contained in:
android-build-team Robot
2020-06-23 03:09:44 +00:00
19 changed files with 201 additions and 48 deletions

View File

@@ -20,9 +20,12 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import com.android.settings.notification.RedactionInterstitial;
import com.google.android.setupcompat.util.WizardManagerHelper;
/**
* Setup Wizard's version of RedactionInterstitial screen. It inherits the logic and basic structure
* from RedactionInterstitial class, and should remain similar to that behaviorally. This class
@@ -46,6 +49,15 @@ public class SetupRedactionInterstitial extends RedactionInterstitial {
PackageManager.DONT_KILL_APP);
}
@Override
protected void onCreate(Bundle savedInstance) {
// Only allow to start the activity from Setup Wizard.
if (!WizardManagerHelper.isAnySetupWizard(getIntent())) {
finish();
}
super.onCreate(savedInstance);
}
@Override
public Intent getIntent() {
Intent modIntent = new Intent(super.getIntent());

View File

@@ -95,9 +95,20 @@ public class FaceSettings extends DashboardFragment {
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 @@ public class FaceSettings extends DashboardFragment {
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 @@ public class FaceSettings extends DashboardFragment {
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
if (!isAvailable(context)) {
if (!isFaceHardwareDetected(context)) {
return null;
}
mControllers = buildPreferenceControllers(context, getSettingsLifecycle());
@@ -314,7 +325,7 @@ public class FaceSettings extends DashboardFragment {
@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 @@ public class FaceSettings extends DashboardFragment {
@Override
protected boolean isPageSearchEnabled(Context context) {
if (isAvailable(context)) {
if (isFaceHardwareDetected(context)) {
return hasEnrolledBiometrics(context);
}
@@ -333,7 +344,10 @@ public class FaceSettings extends DashboardFragment {
@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);

View File

@@ -22,10 +22,10 @@ import android.content.Context;
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 @@ public class FaceSettingsAppPreferenceController extends FaceSettingsPreferenceC
@Override
public boolean isChecked() {
if (!FaceSettings.isAvailable(mContext)) {
if (!FaceSettings.isFaceHardwareDetected(mContext)) {
return false;
}
return Settings.Secure.getIntForUser(
@@ -67,7 +67,7 @@ public class FaceSettingsAppPreferenceController extends FaceSettingsPreferenceC
@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);

View File

@@ -93,7 +93,7 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
@Override
public boolean isChecked() {
if (!FaceSettings.isAvailable(mContext)) {
if (!FaceSettings.isFaceHardwareDetected(mContext)) {
return true;
}
// Set to disabled until we know the true value.

View File

@@ -25,7 +25,6 @@ import android.provider.Settings;
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 @@ public class FaceSettingsConfirmPreferenceController extends FaceSettingsPrefere
@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);

View File

@@ -53,7 +53,7 @@ public class FaceSettingsKeyguardPreferenceController extends FaceSettingsPrefer
@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 class FaceSettingsKeyguardPreferenceController extends FaceSettingsPrefer
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);

View File

@@ -47,7 +47,7 @@ public class FaceSettingsLockscreenBypassPreferenceController
@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 class FaceSettingsLockscreenBypassPreferenceController
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);

View File

@@ -165,7 +165,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
.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);

View File

@@ -41,7 +41,7 @@ public class FaceStatusPreferenceController extends BiometricStatusPreferenceCon
@Override
protected boolean isDeviceSupported() {
return mFaceManager != null && mFaceManager.isHardwareDetected();
return FaceSettings.isFaceHardwareDetected(mContext);
}
@Override

View File

@@ -21,6 +21,7 @@ import static android.provider.Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENA
import android.content.Context;
import android.provider.Settings;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -31,6 +32,7 @@ import com.android.settings.overlay.FeatureFactory;
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 @@ public class AssistGestureSettingsPreferenceController extends GesturePreference
@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;
}

View File

@@ -38,14 +38,14 @@ import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUt
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 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
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 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
@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;

View File

@@ -109,6 +109,7 @@ public class ContextualCardsFragment extends InstrumentedFragment implements
mCardsContainer.setLayoutManager(mLayoutManager);
mContextualCardsAdapter = new ContextualCardsAdapter(context, this /* lifecycleOwner */,
mContextualCardManager);
mCardsContainer.setItemAnimator(null);
mCardsContainer.setAdapter(mContextualCardsAdapter);
mContextualCardManager.setListener(mContextualCardsAdapter);
mCardsContainer.setListener(this);

View File

@@ -22,6 +22,7 @@ import android.app.settings.SettingsEnums;
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 androidx.slice.core.SliceAction;
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 @@ public class EligibleCardChecker implements Callable<ContextualCard> {
// 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;
}

View File

@@ -59,6 +59,11 @@ public abstract class TelephonyTogglePreferenceController extends TogglePreferen
mSetSessionCount.getAndDecrement();
}
@Override
public boolean isSliceable() {
return false;
}
/**
* Get carrier config based on specific subscription id.
*

View File

@@ -48,6 +48,7 @@ import com.android.settingslib.RestrictedLockUtilsInternal;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.GlifLayout;
public class RedactionInterstitial extends SettingsActivity {
@@ -144,7 +145,11 @@ public class RedactionInterstitial extends SettingsActivity {
}
private void onDoneButtonClicked(View view) {
SetupRedactionInterstitial.setEnabled(getContext(), false);
// If the activity starts by Setup Wizard, then skip disable component which avoids the
// framework force closing all activities on the same task when the system is busy.
if (!WizardManagerHelper.isAnySetupWizard(getIntent())) {
SetupRedactionInterstitial.setEnabled(getContext(), false);
}
final RedactionInterstitial activity = (RedactionInterstitial) getActivity();
if (activity != null) {
activity.setResult(RESULT_OK, null);

View File

@@ -23,7 +23,6 @@ import android.content.Context;
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.OnResume;
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 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro
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 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro
mHost = host;
mLockPatternUtils = provider.getLockPatternUtils(context);
mTrustAgentManager = provider.getTrustAgentManager();
mTrustAgentsKeyList = new ArrayList();
if (lifecycle != null) {
lifecycle.addObserver(this);
}
@@ -113,7 +117,7 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro
@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 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro
mSecurityCategory.removePreference(oldAgent);
}
}
mTrustAgentsKeyList.clear();
// Then add new ones.
final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID);
@@ -196,6 +201,7 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro
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);

View File

@@ -143,7 +143,7 @@ public class SettingsSliceProvider extends SliceProvider {
@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 class SettingsSliceProvider extends SliceProvider {
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 @@ public class SettingsSliceProvider extends SliceProvider {
}
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();

View File

@@ -0,0 +1,67 @@
/*
* 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.settings.network.telephony;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class TelephonyTogglePreferenceControllerTest {
private Context mContext;
private FakeTelephonyToggle mFakeTelephonyToggle;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mFakeTelephonyToggle = new FakeTelephonyToggle(mContext, "key");
}
@Test
public void isSliceable_byDefault_shouldReturnFalse() {
assertThat(mFakeTelephonyToggle.isSliceable()).isFalse();
}
private static class FakeTelephonyToggle extends TelephonyTogglePreferenceController {
private FakeTelephonyToggle(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public boolean isChecked() {
return false;
}
@Override
public boolean setChecked(boolean isChecked) {
return false;
}
@Override
public int getAvailabilityStatus(int subId) {
return 0;
}
}
}

View File

@@ -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;
@@ -172,6 +170,26 @@ public class TrustAgentListPreferenceControllerTest {
verify(mCategory, never()).addPreference(any(Preference.class));
}
@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<>();
@@ -190,5 +208,4 @@ public class TrustAgentListPreferenceControllerTest {
assertThat(indexRaws).hasSize(1);
}
}