diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java index 3042667a2e808..b875252a0f1c1 100644 --- a/services/core/java/com/android/server/pm/Computer.java +++ b/services/core/java/com/android/server/pm/Computer.java @@ -387,12 +387,12 @@ public interface Computer extends PackageDataSnapshot { String[] getSystemSharedLibraryNames(); /** - * @return the state if the given package has a state and isn't filtered by visibility. + * @return the state if the given package is installed and isn't filtered by visibility. * Provides no guarantee that the package is in any usable state. */ @Nullable - PackageStateInternal getPackageStateFiltered(@NonNull String packageName, int callingUid, - @UserIdInt int userId); + PackageStateInternal getPackageStateForInstalledAndFiltered(@NonNull String packageName, + int callingUid, @UserIdInt int userId); int checkSignatures(@NonNull String pkg1, @NonNull String pkg2, int userId); diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 6da70fcfc309a..9ee7db3bb11d3 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -4238,10 +4238,11 @@ public class ComputerEngine implements Computer { } @Override - public PackageStateInternal getPackageStateFiltered(@NonNull String packageName, int callingUid, - @UserIdInt int userId) { + public PackageStateInternal getPackageStateForInstalledAndFiltered(@NonNull String packageName, + int callingUid, @UserIdInt int userId) { final PackageStateInternal packageState = getPackageStateInternal(packageName); - if (packageState == null || shouldFilterApplication(packageState, callingUid, userId)) { + if (packageState == null + || shouldFilterApplicationIncludingUninstalled(packageState, callingUid, userId)) { return null; } return packageState; diff --git a/services/core/java/com/android/server/pm/IPackageManagerBase.java b/services/core/java/com/android/server/pm/IPackageManagerBase.java index 9c396b6677b5d..759b6a3d4acab 100644 --- a/services/core/java/com/android/server/pm/IPackageManagerBase.java +++ b/services/core/java/com/android/server/pm/IPackageManagerBase.java @@ -715,8 +715,8 @@ public abstract class IPackageManagerBase extends IPackageManager.Stub { String className) { Objects.requireNonNull(propertyName); Objects.requireNonNull(packageName); - PackageStateInternal packageState = snapshot().getPackageStateFiltered(packageName, - Binder.getCallingUid(), UserHandle.getCallingUserId()); + PackageStateInternal packageState = snapshot().getPackageStateForInstalledAndFiltered( + packageName, Binder.getCallingUid(), UserHandle.getCallingUserId()); if (packageState == null) { return null; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 88ee4c7880625..b5013ae0ccb0a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4461,7 +4461,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService snapshot.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, false /* checkShell */, "clear application data"); - if (snapshot.getPackageStateFiltered(packageName, callingUid, userId) == null) { + if (snapshot.getPackageStateForInstalledAndFiltered( + packageName, callingUid, userId) == null) { if (observer != null) { mHandler.post(() -> { try { @@ -4918,9 +4919,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService @Override public String getPermissionControllerPackageName() { final int callingUid = Binder.getCallingUid(); + final int callingUserId = UserHandle.getUserId(callingUid); final Computer snapshot = snapshotComputer(); - if (snapshot.getPackageStateFiltered(mRequiredPermissionControllerPackage, - callingUid, UserHandle.getUserId(callingUid)) != null) { + if (snapshot.getPackageStateForInstalledAndFiltered( + mRequiredPermissionControllerPackage, callingUid, callingUserId) != null) { return mRequiredPermissionControllerPackage; } @@ -4943,7 +4945,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService snapshot.enforceCrossUserPermission( callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "getSplashScreenTheme"); - PackageStateInternal packageState = filterPackageStateForInstalledAndFiltered(snapshot, + PackageStateInternal packageState = snapshot.getPackageStateForInstalledAndFiltered( packageName, callingUid, userId); return packageState == null ? null : packageState.getUserStateOrDefault(userId).getSplashScreenTheme(); @@ -5350,8 +5352,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService mInjector.getSystemService(AppOpsManager.class) .checkPackage(Binder.getCallingUid(), callerPackageName); - PackageStateInternal packageState = computer.getPackageStateFiltered(packageName, - Binder.getCallingUid(), UserHandle.getCallingUserId()); + PackageStateInternal packageState = computer.getPackageStateForInstalledAndFiltered( + packageName, Binder.getCallingUid(), UserHandle.getCallingUserId()); if (packageState == null) { throw new IllegalArgumentException("Unknown target package " + packageName); } @@ -5420,7 +5422,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService final long callingId = Binder.clearCallingIdentity(); try { final PackageStateInternal packageState = - snapshot.getPackageStateFiltered(packageName, callingUid, userId); + snapshot.getPackageStateForInstalledAndFiltered( + packageName, callingUid, userId); if (packageState == null) { return false; } @@ -5823,7 +5826,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService false /* checkShell */, "setSplashScreenTheme"); enforceOwnerRights(snapshot, packageName, callingUid); - PackageStateInternal packageState = filterPackageStateForInstalledAndFiltered(snapshot, + PackageStateInternal packageState = snapshot.getPackageStateForInstalledAndFiltered( packageName, callingUid, userId); if (packageState == null) { return; @@ -6395,7 +6398,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService public boolean registerInstalledLoadingProgressCallback(String packageName, PackageManagerInternal.InstalledLoadingProgressCallback callback, int userId) { final Computer snapshot = snapshotComputer(); - final PackageStateInternal ps = filterPackageStateForInstalledAndFiltered(snapshot, + final PackageStateInternal ps = snapshot.getPackageStateForInstalledAndFiltered( packageName, Binder.getCallingUid(), userId); if (ps == null) { return false; @@ -6418,7 +6421,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService public IncrementalStatesInfo getIncrementalStatesInfo( @NonNull String packageName, int filterCallingUid, int userId) { final Computer snapshot = snapshotComputer(); - final PackageStateInternal ps = filterPackageStateForInstalledAndFiltered(snapshot, + final PackageStateInternal ps = snapshot.getPackageStateForInstalledAndFiltered( packageName, filterCallingUid, userId); if (ps == null) { return null; @@ -6592,20 +6595,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mSettings.getDisabledSystemPkgLPr(packageName); } - @Nullable - private PackageStateInternal filterPackageStateForInstalledAndFiltered( - @NonNull Computer computer, @NonNull String packageName, int callingUid, - @UserIdInt int userId) { - PackageStateInternal packageState = - computer.getPackageStateInternal(packageName, callingUid); - if (computer.shouldFilterApplicationIncludingUninstalled( - packageState, callingUid, userId)) { - return null; - } else { - return packageState; - } - } - @Deprecated void forEachPackageSetting(Consumer actionLocked) { synchronized (mLock) { diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java index 5f44c6354cff2..f476091766b52 100644 --- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java +++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java @@ -228,7 +228,8 @@ public final class SuspendPackageHelper { continue; } final PackageStateInternal packageState = - snapshot.getPackageStateFiltered(packageNames[i], callingUid, userId); + snapshot.getPackageStateForInstalledAndFiltered( + packageNames[i], callingUid, userId); if (packageState == null) { Slog.w(TAG, "Could not find package setting for package: " + packageNames[i]); unactionablePackages.add(packageNames[i]); diff --git a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java index d7b442c8eaf8a..cacf2cc152c0d 100644 --- a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java +++ b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java @@ -16,6 +16,8 @@ package com.android.server.pm.test.appenumeration; +import static android.Manifest.permission.CLEAR_APP_USER_DATA; + import static com.android.compatibility.common.util.ShellUtils.runShellCommand; import static com.google.common.truth.Truth.assertThat; @@ -25,10 +27,12 @@ import static org.junit.Assert.assertThrows; import android.app.AppGlobals; import android.app.Instrumentation; import android.content.Context; +import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.content.pm.KeySet; import android.content.pm.PackageManager; import android.os.Process; +import android.os.RemoteException; import android.os.UserHandle; import androidx.test.platform.app.InstrumentationRegistry; @@ -37,6 +41,7 @@ import com.android.bedstead.harrier.BedsteadJUnit4; import com.android.bedstead.harrier.DeviceState; import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser; import com.android.bedstead.nene.users.UserReference; +import com.android.compatibility.common.util.TestUtils; import org.junit.After; import org.junit.Before; @@ -46,6 +51,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; +import java.util.concurrent.atomic.AtomicInteger; /** * Verify that app without holding the {@link android.Manifest.permission.INTERACT_ACROSS_USERS} @@ -65,6 +71,8 @@ public class CrossUserPackageVisibilityTests { private static final File SHARED_USER_TEST_APK_FILE = new File(TEST_DATA_DIR, "AppEnumerationSharedUserTestApp.apk"); + private static final long DEFAULT_TIMEOUT_MS = 5000; + @ClassRule @Rule public static final DeviceState sDeviceState = new DeviceState(); @@ -99,6 +107,7 @@ public class CrossUserPackageVisibilityTests { public void tearDown() { uninstallPackage(CROSS_USER_TEST_PACKAGE_NAME); uninstallPackage(SHARED_USER_TEST_PACKAGE_NAME); + mInstrumentation.getUiAutomation().dropShellPermissionIdentity(); } @Test @@ -184,6 +193,34 @@ public class CrossUserPackageVisibilityTests { .isEqualTo(Process.INVALID_UID); } + @Test + public void testClearApplicationUserData_cannotDetectStubPkg() throws Exception { + mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(CLEAR_APP_USER_DATA); + assertThat(clearApplicationUserData(CROSS_USER_TEST_PACKAGE_NAME)).isFalse(); + + installPackageForUser(CROSS_USER_TEST_APK_FILE, mOtherUser); + + assertThat(clearApplicationUserData(CROSS_USER_TEST_PACKAGE_NAME)).isFalse(); + } + + private boolean clearApplicationUserData(String packageName) throws Exception { + final AtomicInteger result = new AtomicInteger(-1); + final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() { + @Override + public void onRemoveCompleted(String removedPkgName, boolean succeeded) + throws RemoteException { + if (removedPkgName.equals(packageName)) { + result.set(succeeded ? 1 : 0); + result.notifyAll(); + } + } + }; + mIPackageManager.clearApplicationUserData(packageName, localObserver, mCurrentUser.id()); + TestUtils.waitOn(result, () -> result.get() != -1, DEFAULT_TIMEOUT_MS, + "clearApplicationUserData: " + packageName); + return result.get() == 1; + } + private static void installPackage(File apk) { installPackageForUser(apk, null, false /* forceQueryable */); }