Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96471dbe authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Merge "Unsuspending packages when a PO or DO is set" into pi-dev am:...

Merge "Merge "Unsuspending packages when a PO or DO is set" into pi-dev am: 24e913e5" into pi-dev-plus-aosp
parents c7a55ad4 2ba61c57
Loading
Loading
Loading
Loading
+52 −17
Original line number Diff line number Diff line
@@ -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,15 +14259,38 @@ 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<>();
            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 && packageName.equals(pus.suspendingPackage)) {
                if (pus.suspended && packagePredicate.test(pus.suspendingPackage)) {
                    ps.setSuspended(false, null, null, null, null, userId);
                    affectedPackages.add(ps.name);
                }
@@ -14281,7 +14305,6 @@ public class PackageManagerService extends IPackageManager.Stub
            mSettings.writePackageRestrictionsLPr(userId);
        }
    }
    }
    @GuardedBy("mPackages")
    private boolean canSuspendPackageForUserLocked(String packageName, int 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
+1 −1
Original line number Diff line number Diff line
@@ -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"
+1 −0
Original line number Diff line number Diff line
@@ -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" />
+79 −1
Original line number Diff line number Diff line
@@ -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));
    }