summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin F. Haggerty <haggertk@lineageos.org>2020-05-05 07:27:40 -0600
committerKevin F. Haggerty <haggertk@lineageos.org>2020-05-05 07:27:40 -0600
commit5df8608656b363f13049855431e2618dd153edaf (patch)
tree86fbabfd8a6b3a8ea13600745f92bdc24df3f7b3
parente740651c8005fa64e0f022fb33c711a72a4acbcc (diff)
parent39c9bf27471f6454202236f88c247fef4c4b2b2e (diff)
downloadandroid_frameworks_base-lineage-16.0.tar.gz
android_frameworks_base-lineage-16.0.tar.bz2
android_frameworks_base-lineage-16.0.zip
Merge tag 'android-9.0.0_r56' of https://android.googlesource.com/platform/frameworks/base into staging/lineage-16.0_merge-android-9.0.0_r56lineage-16.0
Android 9.0.0 release 56 * tag 'android-9.0.0_r56' of https://android.googlesource.com/platform/frameworks/base: Verify all possible hosts that match web nav RESTRICT AUTOMERGE Prevent accessing companion records from arbitrary uids Revert "DO NOT MERGE - Kill apps outright for API contract violations" RESTRICT AUTOMERGE Use consistent calling uid and package in navigateUpTo RESTRICT AUTOMERGE Create separated tasks for different apps from startActivities DO NOT MERGE - Kill apps outright for API contract violations DO NOT MERGE Ensure package names read from config are system packages. RESTRICT AUTOMERGE Update keyguard locked state from TrustManagerService Only suspend package from system or shell Change-Id: I678145bad18e8b34e462cde9f79f2952085f5e55
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--keystore/java/android/security/KeyStore.java11
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java15
-rw-r--r--services/core/java/com/android/server/am/ActivityStartController.java21
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java1
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java28
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java16
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java48
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java2
12 files changed, 143 insertions, 27 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 34d26f0da90..af1a6fa9e3c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3141,6 +3141,11 @@
<permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an application to manage the companion devices.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_COMPANION_DEVICES"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
<p>Not for use by third-party applications.
@hide
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index fe05c13c999..6be2da24e63 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -691,6 +691,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);
+ }
+ }
+
public int attestKey(
String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
try {
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index d44fe4dbc45..bf2b83b1b24 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -629,6 +629,11 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
+ "associate USER_ID PACKAGE MAC_ADDRESS\n"
+ "disassociate USER_ID PACKAGE MAC_ADDRESS";
+ ShellCmd() {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_COMPANION_DEVICES, "ShellCmd");
+ }
+
@Override
public int onCommand(String cmd) {
switch (cmd) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f7b2c403aa6..29adc788dfe 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7673,7 +7673,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
@@ -8054,6 +8054,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/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 5f2a65a7016..dddcc9e466a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3945,6 +3945,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
Intent resultData) {
+ if (srec.app == null || srec.app.thread == null) {
+ // 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.getTask();
final ArrayList<ActivityRecord> activities = task.mActivities;
final int start = activities.indexOf(srec);
@@ -3996,14 +4001,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
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(
@@ -4016,10 +4021,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
.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/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index c926503da27..240f01d159a 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -334,6 +334,9 @@ public class ActivityStartController {
} else {
callingPid = callingUid = -1;
}
+ boolean forceNewTask = false;
+ final int filterCallingUid = ActivityStarter.computeResolveFilterUid(
+ callingUid, realCallingUid, UserHandle.USER_NULL);
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mService) {
@@ -353,11 +356,13 @@ public class ActivityStartController {
// Don't modify the client's object!
intent = new Intent(intent);
+ if (forceNewTask) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
- null, userId, ActivityStarter.computeResolveFilterUid(
- callingUid, realCallingUid, UserHandle.USER_NULL));
+ null, userId, filterCallingUid);
// TODO: New, check if this is correct
aInfo = mService.getActivityInfoForUser(aInfo, userId);
@@ -397,7 +402,17 @@ public class ActivityStartController {
return res;
}
- resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
+ final ActivityRecord started = outActivity[0];
+ if (started != null && started.getUid() == filterCallingUid) {
+ // Only the started activity which has the same uid as the source caller can
+ // be the caller of next activity.
+ resultTo = started.appToken;
+ forceNewTask = false;
+ } else {
+ // Different apps not adjacent to the caller are forced to be new task.
+ resultTo = null;
+ forceNewTask = true;
+ }
}
}
} finally {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8ead96ae346..7a005f665a1 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7202,6 +7202,7 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
protected void simulatePackageSuspendBroadcast(boolean suspend, String pkg) {
+ checkCallerIsSystemOrShell();
// only use for testing: mimic receive broadcast that package is (un)suspended
// but does not actually (un)suspend the package
final Bundle extras = new Bundle();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cab17674469..99f4f6fe171 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17855,7 +17855,9 @@ public class PackageManagerService extends IPackageManager.Stub
final int verificationId = mIntentFilterVerificationToken++;
for (PackageParser.Activity a : pkg.activities) {
for (ActivityIntentInfo filter : a.intents) {
- if (filter.handlesWebUris(true) && needsNetworkVerificationLPr(filter)) {
+ // Run verification against hosts mentioned in any web-nav intent filter,
+ // even if the filter matches non-web schemes as well
+ if (filter.handlesWebUris(false) && needsNetworkVerificationLPr(filter)) {
if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
"Verification needed for IntentFilter:" + filter.toString());
mIntentFilterVerifier.addOneIntentFilterVerification(
@@ -20794,7 +20796,29 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
@Override
public String getSystemTextClassifierPackageName() {
- return mContext.getString(R.string.config_defaultTextClassifierPackage);
+ return ensureSystemPackageName(mContext.getString(
+ R.string.config_defaultTextClassifierPackage));
+ }
+
+ @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 c6d85a83f21..dbf96aa9eee 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -20,8 +20,6 @@ import android.app.ActivityManager;
import android.content.Context;
import android.content.ContentResolver;
import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.security.IKeystoreService;
import android.util.Slog;
import com.android.internal.policy.IKeyguardService;
@@ -61,17 +59,12 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub {
private IUsbRestrict mUsbRestrictor = null;
private ContentResolver mContentResolver;
- IKeystoreService mKeystoreService;
-
public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) {
mLockPatternUtils = new LockPatternUtils(context);
mCurrentUserId = ActivityManager.getCurrentUser();
mCallback = callback;
mContentResolver = context.getContentResolver();
- mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager
- .getService("android.security.keystore"));
-
try {
service.addStateMonitorCallback(this);
} catch (RemoteException e) {
@@ -104,11 +97,6 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub {
mIsShowing = showing;
mCallback.onShowingChanged();
- try {
- mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error informing keystore of screen lock", e);
- }
if (mUsbRestrictor == null) {
try {
@@ -144,10 +132,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 f9f4bbfc8eb..0c22f2f1c18 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -47,6 +47,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.ArraySet;
@@ -121,6 +122,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();
@@ -410,6 +438,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,"
@@ -470,6 +502,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);
+ }
+ }
}
}
@@ -992,6 +1033,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();
@@ -1002,6 +1047,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/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 01425ed51b5..55ece4cf03d 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -606,6 +606,19 @@ public class ActivityStackTests extends ActivityTestsBase {
assertTrue(listener.changed);
}
+ @Test
+ public void testNavigateUpTo() {
+ final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask)
+ .setUid(firstActivity.getUid() + 1).build();
+ secondActivity.app.thread = null;
+ // This should do nothing from a non-attached caller (app.thread == null).
+ assertFalse(mStack.navigateUpToLocked(secondActivity /* source record */,
+ firstActivity.intent /* destIntent */, 0 /* resultCode */, null /* resultData */));
+ assertFalse(secondActivity.finishing);
+ assertFalse(firstActivity.finishing);
+ }
+
private void verifyShouldSleepActivities(boolean focusedStack,
boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
mSupervisor.mFocusedStack = focusedStack ? mStack : null;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 1cd111fce0e..6467dbd8570 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -192,6 +192,8 @@ public class ActivityTestsBase {
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.packageName = mComponent.getPackageName();
aInfo.applicationInfo.uid = mUid;
+ aInfo.packageName = mComponent.getPackageName();
+ aInfo.name = mComponent.getClassName();
aInfo.flags |= mActivityFlags;
final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,