diff options
5 files changed, 106 insertions, 6 deletions
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java index fe8c12c8e232..c2a960a95394 100644 --- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java +++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java @@ -418,11 +418,24 @@ public final class SuspendPackageHelper { } String suspendingPackage = null; + String suspendedBySystem = null; + String qasPackage = null; for (int i = 0; i < userState.getSuspendParams().size(); i++) { suspendingPackage = userState.getSuspendParams().keyAt(i); + var suspendParams = userState.getSuspendParams().valueAt(i); if (PLATFORM_PACKAGE_NAME.equals(suspendingPackage)) { - return suspendingPackage; + suspendedBySystem = suspendingPackage; } + if (suspendParams.isQuarantined() && qasPackage == null) { + qasPackage = suspendingPackage; + } + } + // Precedence: quarantined, then system, then suspending. + if (qasPackage != null) { + return qasPackage; + } + if (suspendedBySystem != null) { + return suspendedBySystem; } return suspendingPackage; } diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index 92665af1075b..4929df8061b2 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; import static android.os.Process.SYSTEM_UID; import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER; @@ -49,7 +50,6 @@ import android.compat.annotation.EnabledAfter; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; -import android.os.Build; import android.os.Process; import android.os.UserHandle; import android.provider.DeviceConfig; @@ -86,7 +86,7 @@ public class BackgroundActivityStartController { private static final int NO_PROCESS_UID = -1; /** If enabled the creator will not allow BAL on its behalf by default. */ @ChangeId - @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @EnabledAfter(targetSdkVersion = UPSIDE_DOWN_CAKE) private static final long DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_CREATOR = 296478951; public static final ActivityOptions ACTIVITY_OPTIONS_SYSTEM_DEFINED = @@ -228,6 +228,7 @@ public class BackgroundActivityStartController { private final Intent mIntent; private final WindowProcessController mCallerApp; private final WindowProcessController mRealCallerApp; + private final boolean mIsCallForResult; private BalState(int callingUid, int callingPid, final String callingPackage, int realCallingUid, int realCallingPid, @@ -247,8 +248,10 @@ public class BackgroundActivityStartController { mOriginatingPendingIntent = originatingPendingIntent; mIntent = intent; mRealCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid); - if (originatingPendingIntent == null // not a PendingIntent - || resultRecord != null // sent for result + mIsCallForResult = resultRecord != null; + if (balRequireOptInByPendingIntentCreator() // auto-opt in introduced with this feature + && (originatingPendingIntent == null // not a PendingIntent + || mIsCallForResult) // sent for result ) { // grant BAL privileges unless explicitly opted out mBalAllowedByPiCreatorWithHardening = mBalAllowedByPiCreator = @@ -351,6 +354,19 @@ public class BackgroundActivityStartController { return name + "[debugOnly]"; } + /** @return valid targetSdk or <code>-1</code> */ + private int getTargetSdk(String packageName) { + if (packageName == null) { + return -1; + } + try { + PackageManager pm = mService.mContext.getPackageManager(); + return pm.getTargetSdkVersion(packageName); + } catch (Exception e) { + return -1; + } + } + private boolean hasRealCaller() { return mRealCallingUid != NO_PROCESS_UID; } @@ -368,6 +384,7 @@ public class BackgroundActivityStartController { StringBuilder sb = new StringBuilder(2048); sb.append("[callingPackage: ") .append(getDebugPackageName(mCallingPackage, mCallingUid)); + sb.append("; callingPackageTargetSdk: ").append(getTargetSdk(mCallingPackage)); sb.append("; callingUid: ").append(mCallingUid); sb.append("; callingPid: ").append(mCallingPid); sb.append("; appSwitchState: ").append(mAppSwitchState); @@ -387,10 +404,13 @@ public class BackgroundActivityStartController { .append(mBalAllowedByPiCreatorWithHardening); sb.append("; resultIfPiCreatorAllowsBal: ").append(resultIfPiCreatorAllowsBal); sb.append("; hasRealCaller: ").append(hasRealCaller()); + sb.append("; isCallForResult: ").append(mIsCallForResult); sb.append("; isPendingIntent: ").append(isPendingIntent()); if (hasRealCaller()) { sb.append("; realCallingPackage: ") .append(getDebugPackageName(mRealCallingPackage, mRealCallingUid)); + sb.append("; realCallingPackageTargetSdk: ") + .append(getTargetSdk(mRealCallingPackage)); sb.append("; realCallingUid: ").append(mRealCallingUid); sb.append("; realCallingPid: ").append(mRealCallingPid); sb.append("; realCallingUidHasAnyVisibleWindow: ") diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp index 3d4f866948af..d66b9b956071 100644 --- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp +++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp @@ -182,7 +182,7 @@ static inline IncFsSize verityTreeSizeForFile(IncFsSize fileSize) { auto block_count = 1 + (fileSize - 1) / INCFS_DATA_FILE_BLOCK_SIZE; auto hash_block_count = block_count; - for (auto i = 0; hash_block_count > 1; i++) { + while (hash_block_count > 1) { hash_block_count = (hash_block_count + hash_per_block - 1) / hash_per_block; total_tree_block_count += hash_block_count; } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt index a6ba5d4c3032..7b80aea80035 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt @@ -36,6 +36,7 @@ import org.mockito.MockitoAnnotations open class PackageHelperTestBase { companion object { + const val PLATFORM_PACKAGE_NAME = "android" const val TEST_PACKAGE_1 = "com.android.test.package1" const val TEST_PACKAGE_2 = "com.android.test.package2" const val DEVICE_OWNER_PACKAGE = "com.android.test.owner" diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt index 147303363200..ae53e707a7cc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt @@ -283,6 +283,72 @@ class SuspendPackageHelperTest : PackageHelperTestBase() { } @Test + fun getSuspendingPackagePrecedence() { + val launcherExtras = PersistableBundle() + launcherExtras.putString(TEST_PACKAGE_2, TEST_PACKAGE_2) + val targetPackages = arrayOf(TEST_PACKAGE_2) + // Suspend. + var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + targetPackages, true /* suspended */, null /* appExtras */, launcherExtras, + null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid, + false /* quarantined */) + assertThat(failedNames).isEmpty() + testHandler.flush() + + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), + TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE) + + // Suspend by system. + failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + targetPackages, true /* suspended */, null /* appExtras */, launcherExtras, + null /* dialogInfo */, PLATFORM_PACKAGE_NAME, TEST_USER_ID, deviceOwnerUid, + false /* quarantined */) + assertThat(failedNames).isEmpty() + testHandler.flush() + + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), + TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(PLATFORM_PACKAGE_NAME) + + // QAS by package1. + failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(), + targetPackages, true /* suspended */, null /* appExtras */, launcherExtras, + null /* dialogInfo */, TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid, + true /* quarantined */) + assertThat(failedNames).isEmpty() + testHandler.flush() + + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), + TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(TEST_PACKAGE_1) + + // Un-QAS by package1. + suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(), + targetPackages, { suspendingPackage -> suspendingPackage == TEST_PACKAGE_1 }, + TEST_USER_ID) + testHandler.flush() + + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), + TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(PLATFORM_PACKAGE_NAME) + + // Un-suspend by system. + suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(), + targetPackages, { suspendingPackage -> suspendingPackage == PLATFORM_PACKAGE_NAME }, + TEST_USER_ID) + testHandler.flush() + + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), + TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE) + + // Unsuspend. + suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(), + targetPackages, { suspendingPackage -> suspendingPackage == DEVICE_OWNER_PACKAGE }, + TEST_USER_ID) + testHandler.flush() + + assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(), + TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNull() + } + + @Test fun getSuspendedDialogInfo() { val dialogInfo = SuspendDialogInfo.Builder() .setTitle(TEST_PACKAGE_1).build() |