Merge cherrypicks of ['googleplex-android-review.googlesource.com/33629809', 'googleplex-android-review.googlesource.com/33629810', 'googleplex-android-review.googlesource.com/33646576', 'googleplex-android-review.googlesource.com/33607203', 'googleplex-android-review.googlesource.com/33909851', 'googleplex-android-review.googlesource.com/33751637', 'googleplex-android-review.googlesource.com/33923313', 'googleplex-android-review.googlesource.com/34044915'] into 25Q2-release.

Change-Id: I5f332baa008006699a4c3386d544e38d68db3a31
This commit is contained in:
Android Build Coastguard Worker
2025-08-12 18:52:22 -07:00
12 changed files with 176 additions and 32 deletions

View File

@@ -265,7 +265,14 @@ public class AccountTypePreferenceLoader {
try { try {
// Allows to launch only authenticator owned activities. // Allows to launch only authenticator owned activities.
ApplicationInfo authenticatorAppInf = pm.getApplicationInfo(authDesc.packageName, 0); ApplicationInfo authenticatorAppInf = pm.getApplicationInfo(authDesc.packageName, 0);
return resolvedAppInfo.uid == authenticatorAppInf.uid; if (resolvedAppInfo.uid == authenticatorAppInf.uid) {
// Explicitly set the component to be same as authenticator to
// prevent launching arbitrary activities.
intent.setComponent(resolvedActivityInfo.getComponentName());
return true;
} else {
return false;
}
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
Log.e(TAG, Log.e(TAG,
"Intent considered unsafe due to exception.", "Intent considered unsafe due to exception.",

View File

@@ -50,6 +50,8 @@ import com.google.android.setupdesign.span.LinkSpan;
import com.google.android.setupdesign.template.RequireScrollMixin; import com.google.android.setupdesign.template.RequireScrollMixin;
import com.google.android.setupdesign.util.DynamicColorPalette; import com.google.android.setupdesign.util.DynamicColorPalette;
import java.util.List;
/** /**
* Abstract base class for the intro onboarding activity for biometric enrollment. * Abstract base class for the intro onboarding activity for biometric enrollment.
*/ */
@@ -249,6 +251,19 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
!isScrollNeeded && !enrollmentCompleted ? View.VISIBLE : View.INVISIBLE); !isScrollNeeded && !enrollmentCompleted ? View.VISIBLE : View.INVISIBLE);
} }
@Override
protected void onStart() {
super.onStart();
if (!getPackageName().equals(getCallingPackage())) {
for (String key : List.of(MultiBiometricEnrollHelper.EXTRA_SKIP_PENDING_ENROLL,
MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE,
MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT)) {
getIntent().removeExtra(key);
}
}
}
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
@@ -497,14 +512,15 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
getIntent().removeExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT); getIntent().removeExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT);
} }
protected void removeEnrollNextBiometricIfSkipEnroll(@Nullable Intent data) { private void removeEnrollNextBiometricIfSkipEnroll(@Nullable Intent data) {
if (data != null if (data != null
&& data.getBooleanExtra( && data.getBooleanExtra(
MultiBiometricEnrollHelper.EXTRA_SKIP_PENDING_ENROLL, false)) { MultiBiometricEnrollHelper.EXTRA_SKIP_PENDING_ENROLL, false)) {
removeEnrollNextBiometric(); removeEnrollNextBiometric();
} }
} }
protected void handleBiometricResultSkipOrFinished(int resultCode, @Nullable Intent data) {
private void handleBiometricResultSkipOrFinished(int resultCode, @Nullable Intent data) {
removeEnrollNextBiometricIfSkipEnroll(data); removeEnrollNextBiometricIfSkipEnroll(data);
if (resultCode == RESULT_SKIP) { if (resultCode == RESULT_SKIP) {
onEnrollmentSkipped(data); onEnrollmentSkipped(data);

View File

@@ -95,8 +95,8 @@ public class FaceSettings extends DashboardFragment {
private FaceManager mFaceManager; private FaceManager mFaceManager;
private DevicePolicyManager mDevicePolicyManager; private DevicePolicyManager mDevicePolicyManager;
private int mUserId; private int mUserId;
private int mSensorId; private int mSensorId = -1;
private long mChallenge; private long mChallenge = 0;
private byte[] mToken; private byte[] mToken;
private FaceSettingsAttentionPreferenceController mAttentionController; private FaceSettingsAttentionPreferenceController mAttentionController;
private FaceSettingsRemoveButtonPreferenceController mRemoveController; private FaceSettingsRemoveButtonPreferenceController mRemoveController;
@@ -181,12 +181,19 @@ public class FaceSettings extends DashboardFragment {
mUserManager = context.getSystemService(UserManager.class); mUserManager = context.getSystemService(UserManager.class);
mFaceManager = context.getSystemService(FaceManager.class); mFaceManager = context.getSystemService(FaceManager.class);
mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class); mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
mToken = getIntent().getByteArrayExtra(KEY_TOKEN);
mSensorId = getIntent().getIntExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, -1);
mChallenge = getIntent().getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 0L);
mUserId = getActivity().getIntent().getIntExtra( final SettingsActivity activity = (SettingsActivity) requireActivity();
Intent.EXTRA_USER_ID, UserHandle.myUserId()); final String callingPackage = activity.getInitialCallingPackage();
if (callingPackage == null || !callingPackage.equals(activity.getPackageName())) {
mUserId = UserHandle.myUserId();
} else {
// only allow these extras when called internally by Settings
mToken = getIntent().getByteArrayExtra(KEY_TOKEN);
mSensorId = getIntent().getIntExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, -1);
mChallenge = getIntent().getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 0L);
mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
}
mFaceFeatureProvider = FeatureFactory.getFeatureFactory().getFaceFeatureProvider(); mFaceFeatureProvider = FeatureFactory.getFeatureFactory().getFaceFeatureProvider();
if (mUserManager.getUserInfo(mUserId).isManagedProfile()) { if (mUserManager.getUserInfo(mUserId).isManagedProfile()) {

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.history; package com.android.settings.notification.history;
import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED; import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
@@ -28,9 +29,11 @@ import android.annotation.DrawableRes;
import android.app.ActionBar; import android.app.ActionBar;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.INotificationManager; import android.app.INotificationManager;
import android.app.KeyguardManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.os.Bundle; import android.os.Bundle;
@@ -58,6 +61,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl; import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.NotificationExpandButton; import com.android.internal.widget.NotificationExpandButton;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.NotificationBackend;
@@ -68,6 +72,7 @@ import com.android.settingslib.widget.MainSwitchBar;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -98,6 +103,8 @@ public class NotificationHistoryActivity extends CollapsingToolbarBaseActivity {
private UiEventLogger mUiEventLogger = new UiEventLoggerImpl(); private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
private ArrayList<Integer> mContentRestrictedUsers = new ArrayList<>();
enum NotificationHistoryEvent implements UiEventLogger.UiEventEnum { enum NotificationHistoryEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "User turned on notification history") @UiEvent(doc = "User turned on notification history")
NOTIFICATION_HISTORY_ON(504), NOTIFICATION_HISTORY_ON(504),
@@ -205,14 +212,14 @@ public class NotificationHistoryActivity extends CollapsingToolbarBaseActivity {
final NotificationHistoryRecyclerView rv = final NotificationHistoryRecyclerView rv =
viewForPackage.findViewById(R.id.notification_list); viewForPackage.findViewById(R.id.notification_list);
rv.setAdapter(new NotificationHistoryAdapter(mNm, rv, rv.setAdapter(new NotificationHistoryAdapter(NotificationHistoryActivity.this, mNm, rv,
newCount -> { newCount -> {
count.setText(StringUtil.getIcuPluralsString(this, newCount, count.setText(StringUtil.getIcuPluralsString(this, newCount,
R.string.notification_history_count)); R.string.notification_history_count));
if (newCount == 0) { if (newCount == 0) {
viewForPackage.setVisibility(GONE); viewForPackage.setVisibility(GONE);
} }
}, mUiEventLogger)); }, mUiEventLogger, mContentRestrictedUsers));
((NotificationHistoryAdapter) rv.getAdapter()).onRebuildComplete( ((NotificationHistoryAdapter) rv.getAdapter()).onRebuildComplete(
new ArrayList<>(nhp.notifications)); new ArrayList<>(nhp.notifications));
@@ -249,6 +256,19 @@ public class NotificationHistoryActivity extends CollapsingToolbarBaseActivity {
mPm = getPackageManager(); mPm = getPackageManager();
mUm = getSystemService(UserManager.class); mUm = getSystemService(UserManager.class);
List<UserInfo> users = mUm.getProfiles(getUserId());
for (UserInfo user : users) {
if (Settings.Secure.getIntForUser(getContentResolver(),
LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, user.id) == 0) {
LockPatternUtils lpu = new LockPatternUtils(this);
KeyguardManager km = getSystemService(KeyguardManager.class);
if (lpu.isSecure(user.id) && km.isDeviceLocked(user.id)) {
mContentRestrictedUsers.add(user.id);
}
}
}
// wait for history loading and recent/snooze loading // wait for history loading and recent/snooze loading
mCountdownLatch = new CountDownLatch(2); mCountdownLatch = new CountDownLatch(2);
@@ -419,7 +439,7 @@ public class NotificationHistoryActivity extends CollapsingToolbarBaseActivity {
mSnoozedRv.setLayoutManager(lm); mSnoozedRv.setLayoutManager(lm);
mSnoozedRv.setAdapter( mSnoozedRv.setAdapter(
new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm, new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm,
true, mUiEventLogger)); true, mUiEventLogger, mContentRestrictedUsers));
mSnoozedRv.setNestedScrollingEnabled(false); mSnoozedRv.setNestedScrollingEnabled(false);
if (snoozed == null || snoozed.length == 0) { if (snoozed == null || snoozed.length == 0) {
@@ -435,7 +455,7 @@ public class NotificationHistoryActivity extends CollapsingToolbarBaseActivity {
mDismissedRv.setLayoutManager(dismissLm); mDismissedRv.setLayoutManager(dismissLm);
mDismissedRv.setAdapter( mDismissedRv.setAdapter(
new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm, new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm,
false, mUiEventLogger)); false, mUiEventLogger, mContentRestrictedUsers));
mDismissedRv.setNestedScrollingEnabled(false); mDismissedRv.setNestedScrollingEnabled(false);
if (dismissed == null || dismissed.length == 0) { if (dismissed == null || dismissed.length == 0) {

View File

@@ -22,6 +22,7 @@ import static android.provider.Settings.EXTRA_CONVERSATION_ID;
import android.app.INotificationManager; import android.app.INotificationManager;
import android.app.NotificationHistory.HistoricalNotification; import android.app.NotificationHistory.HistoricalNotification;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.RemoteException; import android.os.RemoteException;
@@ -53,16 +54,23 @@ public class NotificationHistoryAdapter extends
private List<HistoricalNotification> mValues; private List<HistoricalNotification> mValues;
private OnItemDeletedListener mListener; private OnItemDeletedListener mListener;
private UiEventLogger mUiEventLogger; private UiEventLogger mUiEventLogger;
public NotificationHistoryAdapter(INotificationManager nm, private ArrayList<Integer> mContentRestrictedUsers = new ArrayList<>();
Context mContext;
public NotificationHistoryAdapter(Context context,
INotificationManager nm,
NotificationHistoryRecyclerView listView, NotificationHistoryRecyclerView listView,
OnItemDeletedListener listener, OnItemDeletedListener listener,
UiEventLogger uiEventLogger) { UiEventLogger uiEventLogger,
ArrayList<Integer> contentRestrictedUsers) {
mContext = context;
mValues = new ArrayList<>(); mValues = new ArrayList<>();
setHasStableIds(true); setHasStableIds(true);
listView.setOnItemSwipeDeleteListener(this); listView.setOnItemSwipeDeleteListener(this);
mNm = nm; mNm = nm;
mListener = listener; mListener = listener;
mUiEventLogger = uiEventLogger; mUiEventLogger = uiEventLogger;
mContentRestrictedUsers = contentRestrictedUsers;
} }
@Override @Override
@@ -81,8 +89,13 @@ public class NotificationHistoryAdapter extends
public void onBindViewHolder(final @NonNull NotificationHistoryViewHolder holder, public void onBindViewHolder(final @NonNull NotificationHistoryViewHolder holder,
int position) { int position) {
final HistoricalNotification hn = mValues.get(position); final HistoricalNotification hn = mValues.get(position);
holder.setTitle(hn.getTitle()); if (mContentRestrictedUsers.contains(hn.getUserId())) {
holder.setSummary(hn.getText()); holder.setSummary(mContext.getString(
com.android.internal.R.string.notification_hidden_text));
} else {
holder.setTitle(hn.getTitle());
holder.setSummary(hn.getText());
}
holder.setPostedTime(hn.getPostedTimeMs()); holder.setPostedTime(hn.getPostedTimeMs());
final View.OnClickListener onClick = v -> { final View.OnClickListener onClick = v -> {
mUiEventLogger.logWithPosition(NotificationHistoryActivity.NotificationHistoryEvent mUiEventLogger.logWithPosition(NotificationHistoryActivity.NotificationHistoryEvent

View File

@@ -78,9 +78,11 @@ public class NotificationSbnAdapter extends
private List<Integer> mEnabledProfiles = new ArrayList<>(); private List<Integer> mEnabledProfiles = new ArrayList<>();
private boolean mIsSnoozed; private boolean mIsSnoozed;
private UiEventLogger mUiEventLogger; private UiEventLogger mUiEventLogger;
private ArrayList<Integer> mContentRestrictedUsers = new ArrayList<>();
public NotificationSbnAdapter(Context context, PackageManager pm, UserManager um, public NotificationSbnAdapter(Context context, PackageManager pm, UserManager um,
boolean isSnoozed, UiEventLogger uiEventLogger) { boolean isSnoozed, UiEventLogger uiEventLogger,
ArrayList<Integer> contentRestrictedUsers) {
mContext = context; mContext = context;
mPm = pm; mPm = pm;
mUserBadgeCache = new HashMap<>(); mUserBadgeCache = new HashMap<>();
@@ -101,6 +103,7 @@ public class NotificationSbnAdapter extends
// If true, this is the panel for snoozed notifs, otherwise the one for dismissed notifs. // If true, this is the panel for snoozed notifs, otherwise the one for dismissed notifs.
mIsSnoozed = isSnoozed; mIsSnoozed = isSnoozed;
mUiEventLogger = uiEventLogger; mUiEventLogger = uiEventLogger;
mContentRestrictedUsers = contentRestrictedUsers;
} }
@Override @Override
@@ -128,8 +131,13 @@ public class NotificationSbnAdapter extends
holder.setIconBackground(loadBackground(sbn)); holder.setIconBackground(loadBackground(sbn));
holder.setIcon(loadIcon(sbn)); holder.setIcon(loadIcon(sbn));
holder.setPackageLabel(loadPackageLabel(sbn.getPackageName()).toString()); holder.setPackageLabel(loadPackageLabel(sbn.getPackageName()).toString());
holder.setTitle(getTitleString(sbn.getNotification())); if (mContentRestrictedUsers.contains(sbn.getNormalizedUserId())) {
holder.setSummary(getTextString(mContext, sbn.getNotification())); holder.setSummary(mContext.getString(
com.android.internal.R.string.notification_hidden_text));
} else {
holder.setTitle(getTitleString(sbn.getNotification()));
holder.setSummary(getTextString(mContext, sbn.getNotification()));
}
holder.setPostedTime(sbn.getPostTime()); holder.setPostedTime(sbn.getPostTime());
int userId = normalizeUserId(sbn); int userId = normalizeUserId(sbn);
if (!mUserBadgeCache.containsKey(userId)) { if (!mUserBadgeCache.containsKey(userId)) {

View File

@@ -132,7 +132,7 @@ public class ContentProtectionTogglePreferenceController extends TogglePreferenc
UserManager userManager = mContext.getSystemService(UserManager.class); UserManager userManager = mContext.getSystemService(UserManager.class);
if (userManager != null if (userManager != null
&& userManager.isGuestUser() && !userManager.isAdminUser()
&& mSwitchBar != null) { && mSwitchBar != null) {
mSwitchBar.setEnabled(false); mSwitchBar.setEnabled(false);
} }

View File

@@ -17,6 +17,7 @@
package com.android.settings.security; package com.android.settings.security;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@@ -322,15 +323,25 @@ public final class CredentialStorage extends FragmentActivity {
} }
} }
private String getCallingPackageName() {
try {
return ActivityManager.getService().getLaunchedFromPackage(getActivityToken());
} catch (RemoteException re) {
// Error talking to ActivityManager, just give up
return null;
}
}
/** /**
* Check that the caller is either certinstaller or Settings running in a profile of this user. * Check that the caller is either certinstaller or Settings running in a profile of this user.
*/ */
private boolean checkCallerIsCertInstallerOrSelfInProfile() { private boolean checkCallerIsCertInstallerOrSelfInProfile() {
if (TextUtils.equals("com.android.certinstaller", getCallingPackage())) { String callingPackage = getCallingPackageName();
if (TextUtils.equals("com.android.certinstaller", callingPackage)) {
// CertInstaller is allowed to install credentials if it has the same signature as // CertInstaller is allowed to install credentials if it has the same signature as
// Settings package. // Settings package.
return getPackageManager().checkSignatures( return getPackageManager().checkSignatures(
getCallingPackage(), getPackageName()) == PackageManager.SIGNATURE_MATCH; callingPackage, getPackageName()) == PackageManager.SIGNATURE_MATCH;
} }
final int launchedFromUserId; final int launchedFromUserId;

View File

@@ -639,8 +639,11 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
} else if (restrictionsIntent != null) { } else if (restrictionsIntent != null) {
preference.setRestrictions(restrictions); preference.setRestrictions(restrictions);
if (invokeIfCustom && AppRestrictionsFragment.this.isResumed()) { if (invokeIfCustom && AppRestrictionsFragment.this.isResumed()) {
// We don't necessarily trust the given intent to launch its component.
// We will first check it, and only use parts of it that were indeed checked.
final Intent vettedIntent;
try { try {
assertSafeToStartCustomActivity(restrictionsIntent); vettedIntent = assertSafeToStartCustomActivity(restrictionsIntent);
} catch (ActivityNotFoundException | SecurityException e) { } catch (ActivityNotFoundException | SecurityException e) {
// return without startActivity // return without startActivity
Log.e(TAG, "Cannot start restrictionsIntent " + e); Log.e(TAG, "Cannot start restrictionsIntent " + e);
@@ -651,15 +654,20 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
int requestCode = generateCustomActivityRequestCode( int requestCode = generateCustomActivityRequestCode(
RestrictionsResultReceiver.this.preference); RestrictionsResultReceiver.this.preference);
AppRestrictionsFragment.this.startActivityForResult( AppRestrictionsFragment.this.startActivityForResult(
new Intent(restrictionsIntent), requestCode); vettedIntent, requestCode);
} }
} }
} }
private void assertSafeToStartCustomActivity(Intent intent) { /**
* Checks that it is safe to start the custom activity, and, if so, returns a copy of the
* Intent using its vetted components.
*/
private Intent assertSafeToStartCustomActivity(Intent intent) {
EventLog.writeEvent(0x534e4554, "223578534", -1 /* UID */, ""); EventLog.writeEvent(0x534e4554, "223578534", -1 /* UID */, "");
final Intent vettedIntent = new Intent(intent);
ResolveInfo resolveInfo = mPackageManager.resolveActivity( ResolveInfo resolveInfo = mPackageManager.resolveActivity(
intent, PackageManager.MATCH_DEFAULT_ONLY); vettedIntent, PackageManager.MATCH_DEFAULT_ONLY);
if (resolveInfo == null) { if (resolveInfo == null) {
throw new ActivityNotFoundException("No result for resolving " + intent); throw new ActivityNotFoundException("No result for resolving " + intent);
@@ -670,6 +678,12 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
throw new SecurityException("Application " + packageName throw new SecurityException("Application " + packageName
+ " is not allowed to start activity " + intent); + " is not allowed to start activity " + intent);
} }
// We were able to vet the given intent this time. Make a copy using the components
// that were used to do the vetting, since that's as much as we've verified is safe.
vettedIntent.setComponent(activityInfo.getComponentName());
vettedIntent.setPackage(activityInfo.packageName);
return vettedIntent;
} }
} }

View File

@@ -32,11 +32,13 @@ import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.Activity; import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
@@ -64,6 +66,7 @@ import com.android.settings.R;
import com.android.settings.Settings; import com.android.settings.Settings;
import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils; import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.MultiBiometricEnrollHelper;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settings.testutils.shadow.SettingsShadowResources;
@@ -206,6 +209,12 @@ public class FaceEnrollIntroductionTest {
testIntent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON, testIntent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
FaceEnrollOptions.ENROLL_REASON_SETTINGS); FaceEnrollOptions.ENROLL_REASON_SETTINGS);
testIntent.putExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE,
mock(PendingIntent.class));
testIntent.putExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT,
mock(PendingIntent.class));
testIntent.putExtra(MultiBiometricEnrollHelper.EXTRA_SKIP_PENDING_ENROLL, false);
when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn( when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
null /* Simulate no posture intent */); null /* Simulate no posture intent */);
mContext = spy(ApplicationProvider.getApplicationContext()); mContext = spy(ApplicationProvider.getApplicationContext());
@@ -690,4 +699,16 @@ public class FaceEnrollIntroductionTest {
.isEqualTo(FaceEnrollOptions.ENROLL_REASON_SETTINGS); .isEqualTo(FaceEnrollOptions.ENROLL_REASON_SETTINGS);
} }
@Test
public void drops_pendingIntents() {
setupActivity();
mController.start();
Shadows.shadowOf(Looper.getMainLooper()).idle();
final Intent intent = mActivity.getIntent();
assertThat(intent.hasExtra(MultiBiometricEnrollHelper.EXTRA_SKIP_PENDING_ENROLL)).isFalse();
assertThat(intent.hasExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE)).isFalse();
assertThat(intent.hasExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT)).isFalse();
}
} }

View File

@@ -34,6 +34,7 @@ import static org.mockito.Mockito.mock;
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 android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
@@ -44,6 +45,7 @@ import android.hardware.fingerprint.FingerprintEnrollOptions;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Looper;
import android.os.UserManager; import android.os.UserManager;
import android.view.View; import android.view.View;
@@ -55,6 +57,7 @@ import com.android.internal.widget.VerifyCredentialResponse;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.biometrics.BiometricUtils; import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.GatekeeperPasswordProvider; import com.android.settings.biometrics.GatekeeperPasswordProvider;
import com.android.settings.biometrics.MultiBiometricEnrollHelper;
import com.google.android.setupcompat.util.WizardManagerHelper; import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.GlifLayout; import com.google.android.setupdesign.GlifLayout;
@@ -70,6 +73,7 @@ import org.mockito.stubbing.Answer;
import org.robolectric.Robolectric; import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.android.controller.ActivityController; import org.robolectric.android.controller.ActivityController;
import java.util.ArrayList; import java.util.ArrayList;
@@ -353,7 +357,19 @@ public class FingerprintEnrollIntroductionTest {
false); false);
Assert.assertEquals(View.INVISIBLE, Assert.assertEquals(View.INVISIBLE,
mFingerprintEnrollIntroduction.getSecondaryFooterButton().getVisibility()); mFingerprintEnrollIntroduction.getSecondaryFooterButton().getVisibility());
}
@Test
public void drops_pendingIntents() {
setupFingerprintEnrollIntroWith(newExternalPendingIntent());
mController.start();
Shadows.shadowOf(Looper.getMainLooper()).idle();
final Intent intent = mFingerprintEnrollIntroduction.getIntent();
assertThat(intent.hasExtra(MultiBiometricEnrollHelper.EXTRA_SKIP_PENDING_ENROLL)).isFalse();
assertThat(intent.hasExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE)).isFalse();
assertThat(intent.hasExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT)).isFalse();
} }
private Intent newTokenOnlyIntent() { private Intent newTokenOnlyIntent() {
@@ -383,6 +399,15 @@ public class FingerprintEnrollIntroductionTest {
.putExtra(EXTRA_KEY_GK_PW_HANDLE, 1L); .putExtra(EXTRA_KEY_GK_PW_HANDLE, 1L);
} }
private Intent newExternalPendingIntent() {
return newTokenOnlyIntent()
.putExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE,
mock(PendingIntent.class))
.putExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT,
mock(PendingIntent.class))
.putExtra(MultiBiometricEnrollHelper.EXTRA_SKIP_PENDING_ENROLL, false);
}
private VerifyCredentialResponse newGoodCredential(long gkPwHandle, @NonNull byte[] hat) { private VerifyCredentialResponse newGoodCredential(long gkPwHandle, @NonNull byte[] hat) {
return new VerifyCredentialResponse.Builder() return new VerifyCredentialResponse.Builder()
.setGatekeeperPasswordHandle(gkPwHandle) .setGatekeeperPasswordHandle(gkPwHandle)

View File

@@ -85,7 +85,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
@Before @Before
public void setUp() { public void setUp() {
mShadowUserManager = ShadowUserManager.getShadow(); mShadowUserManager = ShadowUserManager.getShadow();
mShadowUserManager.setGuestUser(false); mShadowUserManager.setIsAdminUser(true);
mController = new TestContentProtectionTogglePreferenceController(); mController = new TestContentProtectionTogglePreferenceController();
SettingsMainSwitchPreference switchPreference = new SettingsMainSwitchPreference(mContext); SettingsMainSwitchPreference switchPreference = new SettingsMainSwitchPreference(mContext);
when(mMockPreferenceScreen.findPreference(mController.getPreferenceKey())) when(mMockPreferenceScreen.findPreference(mController.getPreferenceKey()))
@@ -277,8 +277,8 @@ public class ContentProtectionTogglePreferenceControllerTest {
} }
@Test @Test
public void updateState_flagEnabled_noEnforcedAdmin_guestUser_switchBarDisabled() { public void updateState_flagEnabled_noEnforcedAdmin_nonAdminUser_switchBarDisabled() {
mShadowUserManager.setGuestUser(true); mShadowUserManager.setIsAdminUser(false);
mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED); mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED; mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
setupForUpdateState(); setupForUpdateState();
@@ -289,13 +289,15 @@ public class ContentProtectionTogglePreferenceControllerTest {
} }
@Test @Test
public void updateState_flagEnabled_noEnforcedAdmin_nonGuestUser_switchBarEnabled() { public void updateState_flagEnabled_noEnforcedAdmin_adminUser_switchBarEnabled() {
mShadowUserManager.setIsAdminUser(true);
mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED); mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED; mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
setupForUpdateState(); setupForUpdateState();
mController.updateState(mMockSwitchPreference); mController.updateState(mMockSwitchPreference);
// Verify that the switch bar is *not* set to disabled.
verify(mMockSwitchPreference, never()).setEnabled(false); verify(mMockSwitchPreference, never()).setEnabled(false);
} }