diff options
author | Bill Yi <byi@google.com> | 2020-05-04 20:37:46 -0700 |
---|---|---|
committer | Bill Yi <byi@google.com> | 2020-05-05 20:34:22 +0000 |
commit | b61408add5839a01f40809fc05608af244c0e47d (patch) | |
tree | fee91bccbd8c90c79f5a7796f8fa48620cad273f | |
parent | 92bb1f4d21609b0ca13fa857e5b6c94023fd99fe (diff) | |
parent | 62b1d634b63e3c4f346da9b092ea62ab885bd138 (diff) |
Merge android10-qpr2-s3-release to aosp/master - DO NOT MERGE
Change-Id: I7ce0992bd12158655c0f4833fd924c8012386996
Merged-In: I34d1d5f9a751c1d7680a5a5941c39b9fe33a473b
Merged-In: Icd731877c220b0e3b39258812030313cbaba90c0
17 files changed, 214 insertions, 65 deletions
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 7a560c07a365..0feed7383020 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -299,7 +299,8 @@ interface IActivityManager { void handleApplicationStrictModeViolation(in IBinder app, int penaltyMask, in StrictMode.ViolationInfo crashInfo); boolean isTopActivityImmersive(); - void crashApplication(int uid, int initialPid, in String packageName, int userId, in String message); + void crashApplication(int uid, int initialPid, in String packageName, int userId, + in String message, boolean force); @UnsupportedAppUsage String getProviderMimeType(in Uri uri, int userId); // Cause the specified process to dump the specified heap. diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index e9bc8026d25e..d35642e362b1 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -1067,6 +1067,17 @@ public class KeyStore { return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword); } + /** + * Notify keystore about the latest user locked state. This is to support keyguard-bound key. + */ + public void onUserLockedStateChanged(int userHandle, boolean locked) { + try { + mBinder.onKeyguardVisibilityChanged(locked, userHandle); + } catch (RemoteException e) { + Log.w(TAG, "Failed to update user locked state " + userHandle, e); + } + } + private class KeyAttestationCallbackResult { private KeystoreResponse keystoreResponse; private KeymasterCertificateChain certificateChain; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 688e8eb8f2e3..7c49c3f961c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -566,6 +566,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mRoundnessManager.setAnimatedChildren(mChildrenToAddAnimated); mRoundnessManager.setOnRoundingChangedCallback(this::invalidate); addOnExpandedHeightChangedListener(mRoundnessManager::setExpanded); + mLockscreenUserManager.addUserChangedListener(userId -> + updateSensitiveness(false /* animated */)); setOutlineProvider(mOutlineProvider); // Blocking helper manager wants to know the expanded state, update as well. @@ -4602,7 +4604,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private void setHideSensitive(boolean hideSensitive, boolean animate) { + private void updateSensitiveness(boolean animate) { + boolean hideSensitive = mLockscreenUserManager.isAnyProfilePublicMode(); if (hideSensitive != mAmbientState.isHideSensitive()) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -5306,7 +5309,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd SysuiStatusBarStateController state = (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class); - setHideSensitive(publicMode, state.goingToFullShade() /* animate */); + updateSensitiveness(state.goingToFullShade() /* animate */); setDimmed(onKeyguard, state.fromShadeLocked() /* animate */); setExpandingEnabled(!onKeyguard); ActivatableNotificationView activatedChild = getActivatedChild(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 31054260eb15..f2ed3e648220 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -57,6 +57,8 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.EmptyShadeView; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; @@ -119,6 +121,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private MetricsLogger mMetricsLogger; @Mock private NotificationRoundnessManager mNotificationRoundnessManager; @Mock private KeyguardBypassController mKeyguardBypassController; + @Mock private NotificationLockscreenUserManager mLockscreenUserManager; + private UserChangedListener mUserChangedListener; private TestableNotificationEntryManager mEntryManager; private int mOriginalInterruptionModelSetting; @@ -137,7 +141,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mDependency.injectTestDependency( NotificationBlockingHelperManager.class, mBlockingHelperManager); - mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState); + mDependency.injectTestDependency(NotificationLockscreenUserManager.class, + mLockscreenUserManager); + mDependency.injectTestDependency(StatusBarStateController.class, mBarState); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); mDependency.injectTestDependency(NotificationRemoteInputManager.class, mRemoteInputManager); @@ -152,6 +158,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { NotificationShelf notificationShelf = mock(NotificationShelf.class); + ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor + .forClass(UserChangedListener.class); // The actual class under test. You may need to work with this class directly when // testing anonymous class members of mStackScroller, like mMenuEventListener, @@ -174,6 +182,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mStackScroller.setGroupManager(mGroupManager); mStackScroller.setEmptyShadeView(mEmptyShadeView); mStackScroller.setIconAreaController(mNotificationIconAreaController); + verify(mLockscreenUserManager).addUserChangedListener(userChangedCaptor.capture()); + mUserChangedListener = userChangedCaptor.getValue(); // Stub out functionality that isn't necessary to test. doNothing().when(mBar) @@ -247,6 +257,12 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + public void testOnStatePostChange_verifyIfProfileIsPublic() { + mUserChangedListener.onUserChanged(0); + verify(mLockscreenUserManager).isAnyProfilePublicMode(); + } + + @Test public void manageNotifications_visible() { FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 0ba41736ce15..0ba6a5536cbf 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -842,6 +842,15 @@ public final class ActiveServices { } } + void killMisbehavingService(ServiceRecord r, + int appUid, int appPid, String localPackageName) { + synchronized (mAm) { + stopServiceLocked(r); + mAm.crashApplication(appUid, appPid, localPackageName, -1, + "Bad notification for startForeground", true /*force*/); + } + } + IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) { ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), @@ -3946,7 +3955,7 @@ public final class ActiveServices { void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) { mAm.crashApplication(app.uid, app.pid, app.info.packageName, app.userId, "Context.startForegroundService() did not then call Service.startForeground(): " - + serviceRecord); + + serviceRecord, false /*force*/); } void scheduleServiceTimeoutLocked(ProcessRecord proc) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 39ea499f21d0..ece21f667418 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3597,7 +3597,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void crashApplication(int uid, int initialPid, String packageName, int userId, - String message) { + String message, boolean force) { if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: crashApplication() from pid=" @@ -3609,7 +3609,8 @@ public class ActivityManagerService extends IActivityManager.Stub } synchronized(this) { - mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, message); + mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, + message, force); } } @@ -4788,7 +4789,7 @@ public class ActivityManagerService extends IActivityManager.Stub } @GuardedBy("this") - private final boolean attachApplicationLocked(IApplicationThread thread, + private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { // Find the application record that is being attached... either via @@ -5211,6 +5212,9 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public final void attachApplication(IApplicationThread thread, long startSeq) { + if (thread == null) { + throw new SecurityException("Invalid application interface"); + } synchronized (this) { int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 5078b8a14eb2..5ab18d95b84d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -1058,7 +1058,7 @@ final class ActivityManagerShellCommand extends ShellCommand { } catch (NumberFormatException e) { packageName = arg; } - mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash"); + mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash", false); return 0; } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index a4c695067139..bbd2d34e92a6 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -314,20 +314,24 @@ class AppErrors { } void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) { - app.setCrashing(false); - app.crashingReport = null; - app.setNotResponding(false); - app.notRespondingReport = null; if (app.anrDialog == fromDialog) { app.anrDialog = null; } if (app.waitDialog == fromDialog) { app.waitDialog = null; } + killAppImmediateLocked(app, "user-terminated", "user request after error"); + } + + private void killAppImmediateLocked(ProcessRecord app, String reason, String killReason) { + app.setCrashing(false); + app.crashingReport = null; + app.setNotResponding(false); + app.notRespondingReport = null; if (app.pid > 0 && app.pid != MY_PID) { - handleAppCrashLocked(app, "user-terminated" /*reason*/, + handleAppCrashLocked(app, reason, null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/); - app.kill("user request after error", true); + app.kill(killReason, true); } } @@ -341,7 +345,7 @@ class AppErrors { * @param message */ void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, - String message) { + String message, boolean force) { ProcessRecord proc = null; // Figure out which process to kill. We don't trust that initialPid @@ -374,6 +378,14 @@ class AppErrors { } proc.scheduleCrash(message); + if (force) { + // If the app is responsive, the scheduled crash will happen as expected + // and then the delayed summary kill will be a no-op. + final ProcessRecord p = proc; + mService.mHandler.postDelayed( + () -> killAppImmediateLocked(p, "forced", "killed for invalid state"), + 5000L); + } } /** diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index dee8e3b285a7..c408695bcb66 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -798,6 +798,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN final String localPackageName = packageName; final int localForegroundId = foregroundId; final Notification _foregroundNoti = foregroundNoti; + final ServiceRecord record = this; ams.mHandler.post(new Runnable() { public void run() { NotificationManagerInternal nm = LocalServices.getService( @@ -896,10 +897,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN Slog.w(TAG, "Error showing notification for service", e); // If it gave us a garbage notification, it doesn't // get to be foreground. - ams.setServiceForeground(instanceName, ServiceRecord.this, - 0, null, 0, 0); - ams.crashApplication(appUid, appPid, localPackageName, -1, - "Bad notification for startForeground: " + e); + ams.mServices.killMisbehavingService(record, + appUid, appPid, localPackageName); } } }); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index a2f191444b63..2d39e9169245 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -920,7 +920,7 @@ public class NotificationManagerService extends SystemService { () -> mAm.crashApplication(uid, initialPid, pkg, -1, "Bad notification(tag=" + tag + ", id=" + id + ") posted from package " + pkg + ", crashing app(uid=" + uid + ", pid=" + initialPid + "): " - + message)); + + message, true /* force */)); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e82102f3379d..50bbfa96bfab 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3004,8 +3004,7 @@ public class PackageManagerService extends IPackageManager.Stub mWellbeingPackage = getWellbeingPackageName(); mDocumenterPackage = getDocumenterPackageName(); - mConfiguratorPackage = - mContext.getString(R.string.config_deviceConfiguratorPackageName); + mConfiguratorPackage = getDeviceConfiguratorPackageName(); mAppPredictionServicePackage = getAppPredictionServicePackageName(); mIncidentReportApproverPackage = getIncidentReportApproverPackageName(); mTelephonyPackages = getTelephonyPackageNames(); @@ -20537,7 +20536,8 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String getSystemTextClassifierPackageName() { - return mContext.getString(R.string.config_defaultTextClassifierPackage); + return ensureSystemPackageName(mContext.getString( + R.string.config_defaultTextClassifierPackage)); } @Override @@ -20547,7 +20547,7 @@ public class PackageManagerService extends IPackageManager.Stub if (flattenedComponentName != null) { ComponentName componentName = ComponentName.unflattenFromString(flattenedComponentName); if (componentName != null && componentName.getPackageName() != null) { - return componentName.getPackageName(); + return ensureSystemPackageName(componentName.getPackageName()); } } return null; @@ -20572,9 +20572,15 @@ public class PackageManagerService extends IPackageManager.Stub } } + @Nullable + private String getDeviceConfiguratorPackageName() { + return ensureSystemPackageName(mContext.getString( + R.string.config_deviceConfiguratorPackageName)); + } + @Override public String getWellbeingPackageName() { - return mContext.getString(R.string.config_defaultWellbeingPackage); + return ensureSystemPackageName(mContext.getString(R.string.config_defaultWellbeingPackage)); } @Override @@ -20589,7 +20595,7 @@ public class PackageManagerService extends IPackageManager.Stub if (appPredictionServiceComponentName == null) { return null; } - return appPredictionServiceComponentName.getPackageName(); + return ensureSystemPackageName(appPredictionServiceComponentName.getPackageName()); } @Override @@ -20606,11 +20612,33 @@ public class PackageManagerService extends IPackageManager.Stub if (systemCaptionsServiceComponentName == null) { return null; } - return systemCaptionsServiceComponentName.getPackageName(); + return ensureSystemPackageName(systemCaptionsServiceComponentName.getPackageName()); } public String getIncidentReportApproverPackageName() { - return mContext.getString(R.string.config_incidentReportApproverPackage); + return ensureSystemPackageName(mContext.getString( + R.string.config_incidentReportApproverPackage)); + } + + @Nullable + private String ensureSystemPackageName(@Nullable String packageName) { + if (packageName == null) { + return null; + } + long token = Binder.clearCallingIdentity(); + try { + if (getPackageInfo(packageName, MATCH_FACTORY_ONLY, UserHandle.USER_SYSTEM) == null) { + PackageInfo packageInfo = getPackageInfo(packageName, 0, UserHandle.USER_SYSTEM); + if (packageInfo != null) { + EventLog.writeEvent(0x534e4554, "145981139", packageInfo.applicationInfo.uid, + ""); + } + return null; + } + } finally { + Binder.restoreCallingIdentity(token); + } + return packageName; } @Override diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java index f78d2639df1a..add0b01f1879 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java @@ -19,8 +19,6 @@ package com.android.server.policy.keyguard; import android.app.ActivityManager; import android.content.Context; import android.os.RemoteException; -import android.os.ServiceManager; -import android.security.keystore.IKeystoreService; import android.util.Slog; import com.android.internal.policy.IKeyguardService; @@ -53,16 +51,11 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { private final LockPatternUtils mLockPatternUtils; private final StateCallback mCallback; - IKeystoreService mKeystoreService; - public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) { mLockPatternUtils = new LockPatternUtils(context); mCurrentUserId = ActivityManager.getCurrentUser(); mCallback = callback; - mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager - .getService("android.security.keystore")); - try { service.addStateMonitorCallback(this); } catch (RemoteException e) { @@ -95,23 +88,6 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { mIsShowing = showing; mCallback.onShowingChanged(); - int retry = 2; - while (retry > 0) { - try { - mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId); - break; - } catch (RemoteException e) { - if (retry == 2) { - Slog.w(TAG, "Error informing keystore of screen lock. Keystore may have died" - + " -> refreshing service token and retrying"); - mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager - .getService("android.security.keystore")); - } else { - Slog.e(TAG, "Error informing keystore of screen lock after retrying once", e); - } - --retry; - } - } } @Override // Binder interface @@ -123,10 +99,6 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { mCurrentUserId = userId; } - private synchronized int getCurrentUser() { - return mCurrentUserId; - } - @Override // Binder interface public void onInputRestrictedStateChanged(boolean inputRestricted) { mInputRestricted = inputRestricted; diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 7408dd40b5ca..5f5cd3c46117 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -53,6 +53,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.security.KeyStore; import android.service.trust.TrustAgentService; import android.text.TextUtils; import android.util.ArrayMap; @@ -135,6 +136,33 @@ public class TrustManagerService extends SystemService { @GuardedBy("mUserIsTrusted") private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray(); + /** + * Stores the locked state for users on the device. There are three different type of users + * which are handled slightly differently: + * <ul> + * <li> Users with real keyguard + * These are users who can be switched to ({@link UserInfo#supportsSwitchToByUser()}). Their + * locked state is derived by a combination of user secure state, keyguard state, trust agent + * decision and biometric authentication result. These are updated via + * {@link #refreshDeviceLockedForUser(int)} and result stored in {@link #mDeviceLockedForUser}. + * <li> Managed profiles with unified challenge + * Managed profile with unified challenge always shares the same locked state as their parent, + * so their locked state is not recorded in {@link #mDeviceLockedForUser}. Instead, + * {@link ITrustManager#isDeviceLocked(int)} always resolves their parent user handle and + * queries its locked state instead. + * <li> Managed profiles with separate challenge + * Locked state for profile with separate challenge is determined by other parts of the + * framework (mostly PowerManager) and pushed to TrustManagerService via + * {@link ITrustManager#setDeviceLockedForUser(int, boolean)}. Although in a corner case when + * the profile has a separate but empty challenge, setting its {@link #mDeviceLockedForUser} to + * {@code false} is actually done by {@link #refreshDeviceLockedForUser(int)}. + * </ul> + * TODO: Rename {@link ITrustManager#setDeviceLockedForUser(int, boolean)} to + * {@code setDeviceLockedForProfile} to better reflect its purpose. Unifying + * {@code setDeviceLockedForProfile} and {@link #setDeviceLockedForUser} would also be nice. + * At the moment they both update {@link #mDeviceLockedForUser} but have slightly different + * side-effects: one notifies trust agents while the other sends out a broadcast. + */ @GuardedBy("mDeviceLockedForUser") private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray(); @@ -601,6 +629,10 @@ public class TrustManagerService extends SystemService { } } + /** + * Update the user's locked state. Only applicable to users with a real keyguard + * ({@link UserInfo#supportsSwitchToByUser}) and unsecured managed profiles. + */ private void refreshDeviceLockedForUser(int userId) { if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) { Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle," @@ -661,6 +693,15 @@ public class TrustManagerService extends SystemService { } if (changed) { dispatchDeviceLocked(userId, locked); + + KeyStore.getInstance().onUserLockedStateChanged(userId, locked); + // Also update the user's profiles who have unified challenge, since they + // share the same unlocked state (see {@link #isDeviceLocked(int)}) + for (int profileHandle : mUserManager.getEnabledProfileIds(userId)) { + if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(profileHandle)) { + KeyStore.getInstance().onUserLockedStateChanged(profileHandle, locked); + } + } } } @@ -1194,6 +1235,10 @@ public class TrustManagerService extends SystemService { return "0x" + Integer.toHexString(i); } + /** + * Changes the lock status for the given user. This is only applicable to managed profiles, + * other users should be handled by Keyguard. + */ @Override public void setDeviceLockedForUser(int userId, boolean locked) { enforceReportPermission(); @@ -1204,6 +1249,9 @@ public class TrustManagerService extends SystemService { synchronized (mDeviceLockedForUser) { mDeviceLockedForUser.put(userId, locked); } + + KeyStore.getInstance().onUserLockedStateChanged(userId, locked); + if (locked) { try { ActivityManager.getService().notifyLockedProfile(userId); diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 848971d3b044..1592f239fd2e 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -4268,6 +4268,11 @@ class ActivityStack extends ConfigurationContainer { final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, Intent resultData) { + if (!srec.attachedToProcess()) { + // Nothing to do if the caller is not attached, because this method should be called + // from an alive activity. + return false; + } final TaskRecord task = srec.getTaskRecord(); final ArrayList<ActivityRecord> activities = task.mActivities; final int start = activities.indexOf(srec); @@ -4321,14 +4326,14 @@ class ActivityStack extends ConfigurationContainer { } if (parent != null && foundParentInTask) { + final int callingUid = srec.info.applicationInfo.uid; final int parentLaunchMode = parent.info.launchMode; final int destIntentFlags = destIntent.getFlags(); if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK || parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP || (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { - parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent, - srec.packageName); + parent.deliverNewIntentLocked(callingUid, destIntent, srec.packageName); } else { try { ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo( @@ -4341,10 +4346,10 @@ class ActivityStack extends ConfigurationContainer { .setActivityInfo(aInfo) .setResultTo(parent.appToken) .setCallingPid(-1) - .setCallingUid(parent.launchedFromUid) - .setCallingPackage(parent.launchedFromPackage) + .setCallingUid(callingUid) + .setCallingPackage(srec.packageName) .setRealCallingPid(-1) - .setRealCallingUid(parent.launchedFromUid) + .setRealCallingUid(callingUid) .setComponentSpecified(true) .execute(); foundParentInTask = res == ActivityManager.START_SUCCESS; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 5b697ee89602..f37698de34d5 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2763,6 +2763,11 @@ class ActivityStarter { return mRequest.intent; } + @VisibleForTesting + int getCallingUid() { + return mRequest.callingUid; + } + ActivityStarter setReason(String reason) { mRequest.reason = reason; return this; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index bde0ef6aa39e..ff27b9bb1c9e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -28,7 +28,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; import static com.android.server.wm.ActivityStack.ActivityState.FINISHING; @@ -54,8 +54,11 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import android.app.ActivityManager; +import android.app.IApplicationThread; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.os.UserHandle; @@ -82,8 +85,9 @@ public class ActivityStackTests extends ActivityTestsBase { @Before public void setUp() throws Exception { mDefaultDisplay = mRootActivityContainer.getDefaultDisplay(); - mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, - true /* onTop */)); + mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, + true /* onTop */); + spyOn(mStack); mTask = new TaskBuilder(mSupervisor).setStack(mStack).build(); } @@ -1078,6 +1082,37 @@ public class ActivityStackTests extends ActivityTestsBase { assertTrue(listener.mChanged); } + @Test + public void testNavigateUpTo() { + final ActivityStartController controller = mock(ActivityStartController.class); + final ActivityStarter starter = new ActivityStarter(controller, + mService, mService.mStackSupervisor, mock(ActivityStartInterceptor.class)); + doReturn(controller).when(mService).getActivityStartController(); + spyOn(starter); + doReturn(ActivityManager.START_SUCCESS).when(starter).execute(); + + final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); + final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask) + .setUid(firstActivity.getUid() + 1).build(); + doReturn(starter).when(controller).obtainStarter(eq(firstActivity.intent), anyString()); + + final IApplicationThread thread = secondActivity.app.getThread(); + secondActivity.app.setThread(null); + // This should do nothing from a non-attached caller. + assertFalse(mStack.navigateUpToLocked(secondActivity /* source record */, + firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */)); + + secondActivity.app.setThread(thread); + assertTrue(mStack.navigateUpToLocked(secondActivity /* source record */, + firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */)); + // The firstActivity uses default launch mode, so the activities between it and itself will + // be finished. + assertTrue(secondActivity.finishing); + assertTrue(firstActivity.finishing); + // The calling uid of the new activity should be the current real caller. + assertEquals(secondActivity.getUid(), starter.getCallingUid()); + } + private void verifyShouldSleepActivities(boolean focusedStack, boolean keyguardGoingAway, boolean displaySleeping, boolean expected) { final ActivityDisplay display = mock(ActivityDisplay.class); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java index 84bdecb86826..f94f00203521 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java @@ -290,6 +290,7 @@ class ActivityTestsBase { aInfo.applicationInfo.packageName = mComponent.getPackageName(); aInfo.applicationInfo.uid = mUid; aInfo.packageName = mComponent.getPackageName(); + aInfo.name = mComponent.getClassName(); if (mTargetActivity != null) { aInfo.targetActivity = mTargetActivity; } |