summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2018-05-24 03:01:38 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-05-24 03:01:38 +0000
commit24e913e5a84507f0c683ed492d87744c4b5e05af (patch)
tree0691baf8d024f3d36c194961287980b51503e8c2
parent062c050d01972035b1d758a9649714ac879dea8d (diff)
parent77e2245e713a30c81c1ac44a7635c7ffef193461 (diff)
Merge "Unsuspending packages when a PO or DO is set" into pi-dev
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java69
-rw-r--r--services/tests/servicestests/AndroidManifest.xml2
-rw-r--r--services/tests/servicestests/AndroidTest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java80
4 files changed, 133 insertions, 19 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9886a07c0a49..d5f936b28b8c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -367,6 +367,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
/**
* Keep track of all those APKs everywhere.
@@ -14258,28 +14259,50 @@ public class PackageManagerService extends IPackageManager.Stub
* @param packageName The package holding {@link Manifest.permission#SUSPEND_APPS} permission
* @param affectedUser The user for which the changes are taking place.
*/
- void unsuspendForSuspendingPackage(String packageName, int affectedUser) {
+ void unsuspendForSuspendingPackage(final String packageName, int affectedUser) {
final int[] userIds = (affectedUser == UserHandle.USER_ALL) ? sUserManager.getUserIds()
: new int[] {affectedUser};
for (int userId : userIds) {
- List<String> affectedPackages = new ArrayList<>();
- synchronized (mPackages) {
- for (PackageSetting ps : mSettings.mPackages.values()) {
- final PackageUserState pus = ps.readUserState(userId);
- if (pus.suspended && packageName.equals(pus.suspendingPackage)) {
- ps.setSuspended(false, null, null, null, null, userId);
- affectedPackages.add(ps.name);
- }
+ unsuspendForSuspendingPackages(packageName::equals, userId);
+ }
+ }
+
+ /**
+ * Immediately unsuspends any packages in the given users not suspended by the platform or root.
+ * To be called when a profile owner or a device owner is added.
+ *
+ * <p><b>Should not be used on a frequent code path</b> as it flushes state to disk
+ * synchronously
+ *
+ * @param userIds The users for which to unsuspend packages
+ */
+ void unsuspendForNonSystemSuspendingPackages(ArraySet<Integer> userIds) {
+ final int sz = userIds.size();
+ for (int i = 0; i < sz; i++) {
+ unsuspendForSuspendingPackages(
+ (suspendingPackage) -> !PLATFORM_PACKAGE_NAME.equals(suspendingPackage),
+ userIds.valueAt(i));
+ }
+ }
+
+ private void unsuspendForSuspendingPackages(Predicate<String> packagePredicate, int userId) {
+ final List<String> affectedPackages = new ArrayList<>();
+ synchronized (mPackages) {
+ for (PackageSetting ps : mSettings.mPackages.values()) {
+ final PackageUserState pus = ps.readUserState(userId);
+ if (pus.suspended && packagePredicate.test(pus.suspendingPackage)) {
+ ps.setSuspended(false, null, null, null, null, userId);
+ affectedPackages.add(ps.name);
}
}
- if (!affectedPackages.isEmpty()) {
- final String[] packageArray = affectedPackages.toArray(
- new String[affectedPackages.size()]);
- sendMyPackageSuspendedOrUnsuspended(packageArray, false, null, userId);
- sendPackagesSuspendedForUser(packageArray, userId, false, null);
- // Write package restrictions immediately to avoid an inconsistent state.
- mSettings.writePackageRestrictionsLPr(userId);
- }
+ }
+ if (!affectedPackages.isEmpty()) {
+ final String[] packageArray = affectedPackages.toArray(
+ new String[affectedPackages.size()]);
+ sendMyPackageSuspendedOrUnsuspended(packageArray, false, null, userId);
+ sendPackagesSuspendedForUser(packageArray, userId, false, null);
+ // Write package restrictions immediately to avoid an inconsistent state.
+ mSettings.writePackageRestrictionsLPr(userId);
}
}
@@ -23977,6 +24000,18 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
SparseArray<String> profileOwnerPackages) {
mProtectedPackages.setDeviceAndProfileOwnerPackages(
deviceOwnerUserId, deviceOwnerPackage, profileOwnerPackages);
+
+ final ArraySet<Integer> usersWithPoOrDo = new ArraySet<>();
+ if (deviceOwnerPackage != null) {
+ usersWithPoOrDo.add(deviceOwnerUserId);
+ }
+ final int sz = profileOwnerPackages.size();
+ for (int i = 0; i < sz; i++) {
+ if (profileOwnerPackages.valueAt(i) != null) {
+ usersWithPoOrDo.add(profileOwnerPackages.keyAt(i));
+ }
+ }
+ unsuspendForNonSystemSuspendingPackages(usersWithPoOrDo);
}
@Override
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 2ac9df9c975c..a8efe819e518 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -70,7 +70,7 @@
<uses-sdk android:minSdkVersion="1"
android:targetSdkVersion="26"/>
- <application>
+ <application android:testOnly="true">
<uses-library android:name="android.test.runner" />
<service android:name="com.android.server.accounts.TestAccountType1AuthenticatorService"
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index 8f989df23b1b..5ac68d4b69d4 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="test-suite-tag" value="apct-instrumentation" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
<option name="test-file-name" value="FrameworksServicesTests.apk" />
<option name="test-file-name" value="JobTestApp.apk" />
<option name="test-file-name" value="ConnTestApp.apk" />
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index b8922eb4cc94..c186e48e8794 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.app.AppGlobals;
import android.content.BroadcastReceiver;
@@ -59,6 +60,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
@@ -97,6 +99,9 @@ public class SuspendPackagesTest {
private AppCommunicationReceiver mAppCommsReceiver;
private StubbedCallback mTestCallback;
private UiDevice mUiDevice;
+ private ComponentName mDeviceAdminComponent;
+ private boolean mPoSet;
+ private boolean mDoSet;
private static final class AppCommunicationReceiver extends BroadcastReceiver {
private Context context;
@@ -163,6 +168,8 @@ public class SuspendPackagesTest {
mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
mReceiverHandler = new Handler(Looper.getMainLooper());
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mDeviceAdminComponent = new ComponentName(mContext,
+ "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1");
IPackageManager ipm = AppGlobals.getPackageManager();
try {
// Otherwise implicit broadcasts will not be delivered.
@@ -469,12 +476,83 @@ public class SuspendPackagesTest {
TEST_APP_PACKAGE_NAME, receivedPackageName);
}
+ private boolean setProfileOwner() throws IOException {
+ final String result = mUiDevice.executeShellCommand("dpm set-profile-owner --user cur "
+ + mDeviceAdminComponent.flattenToString());
+ return mPoSet = result.trim().startsWith("Success");
+ }
+
+ private boolean setDeviceOwner() throws IOException {
+ final String result = mUiDevice.executeShellCommand("dpm set-device-owner --user cur "
+ + mDeviceAdminComponent.flattenToString());
+ return mDoSet = result.trim().startsWith("Success");
+ }
+
+ private void removeProfileOrDeviceOwner() throws IOException {
+ if (mPoSet || mDoSet) {
+ mUiDevice.executeShellCommand("dpm remove-active-admin --user cur "
+ + mDeviceAdminComponent.flattenToString());
+ mPoSet = mDoSet = false;
+ }
+ }
+
+ @Test
+ public void testCannotSuspendWhenProfileOwner() throws IOException {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
+ assertTrue("Profile-owner could not be set", setProfileOwner());
+ try {
+ suspendTestPackage(null, null, null);
+ fail("Suspend succeeded. Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException uex) {
+ }
+ }
+
+ @Test
+ public void testCannotSuspendWhenDeviceOwner() throws IOException {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
+ assertTrue("Device-owner could not be set", setDeviceOwner());
+ try {
+ suspendTestPackage(null, null, null);
+ fail("Suspend succeeded. Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException uex) {
+ }
+ }
+
+ @Test
+ public void testPackageUnsuspendedOnAddingDeviceOwner() throws IOException {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
+ mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED);
+ mAppCommsReceiver.drainPendingBroadcasts();
+ suspendTestPackage(null, null, null);
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
+ assertTrue("Device-owner could not be set", setDeviceOwner());
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
+ }
+
+ @Test
+ public void testPackageUnsuspendedOnAddingProfileOwner() throws IOException {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
+ mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED);
+ mAppCommsReceiver.drainPendingBroadcasts();
+ suspendTestPackage(null, null, null);
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
+ assertTrue("Profile-owner could not be set", setProfileOwner());
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
+ }
+
@After
- public void tearDown() {
+ public void tearDown() throws IOException {
mAppCommsReceiver.unregister();
if (mTestCallback != null) {
mLauncherApps.unregisterCallback(mTestCallback);
}
+ removeProfileOrDeviceOwner();
mContext.sendBroadcast(new Intent(ACTION_FINISH_TEST_ACTIVITY)
.setPackage(TEST_APP_PACKAGE_NAME));
}