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

Commit c650ef8a authored by Jing Ji's avatar Jing Ji Committed by Automerger Merge Worker
Browse files

Merge "Allow service auto-restarts when its dependency is force-stopped" into...

Merge "Allow service auto-restarts when its dependency is force-stopped" into sc-v2-dev am: df6ae85d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16387368

Change-Id: Ieb518c1bbf1a270065724104312b3e9abf25d4b7
parents 6dd34c5a df6ae85d
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -4190,7 +4190,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            didSomething |= mProcessList.killPackageProcessesLSP(packageName, appId, userId,
            didSomething |= mProcessList.killPackageProcessesLSP(packageName, appId, userId,
                    ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit,
                    ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit,
                    evenPersistent, true /* setRemoved */,
                    evenPersistent, true /* setRemoved */, uninstalling,
                    packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
                    packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
                    : ApplicationExitInfo.REASON_USER_REQUESTED,
                    : ApplicationExitInfo.REASON_USER_REQUESTED,
                    ApplicationExitInfo.SUBREASON_UNKNOWN,
                    ApplicationExitInfo.SUBREASON_UNKNOWN,
@@ -7227,6 +7227,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                            ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
                            ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
                            true /* callerWillRestart */, true /* doit */,
                            true /* callerWillRestart */, true /* doit */,
                            true /* evenPersistent */, false /* setRemoved */,
                            true /* evenPersistent */, false /* setRemoved */,
                            false /* uninstalling */,
                            ApplicationExitInfo.REASON_OTHER,
                            ApplicationExitInfo.REASON_OTHER,
                            ApplicationExitInfo.SUBREASON_KILL_UID,
                            ApplicationExitInfo.SUBREASON_KILL_UID,
                            reason != null ? reason : "kill uid");
                            reason != null ? reason : "kill uid");
@@ -7248,6 +7249,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                            ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
                            ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
                            true /* callerWillRestart */, true /* doit */,
                            true /* callerWillRestart */, true /* doit */,
                            true /* evenPersistent */, false /* setRemoved */,
                            true /* evenPersistent */, false /* setRemoved */,
                            false /* uninstalling */,
                            ApplicationExitInfo.REASON_PERMISSION_CHANGE,
                            ApplicationExitInfo.REASON_PERMISSION_CHANGE,
                            ApplicationExitInfo.SUBREASON_UNKNOWN,
                            ApplicationExitInfo.SUBREASON_UNKNOWN,
                            reason != null ? reason : "kill uid");
                            reason != null ? reason : "kill uid");
+32 −10
Original line number Original line Diff line number Diff line
@@ -2751,8 +2751,8 @@ public final class ProcessList {
            int reasonCode, int subReason, String reason) {
            int reasonCode, int subReason, String reason) {
        return killPackageProcessesLSP(packageName, appId, userId, minOomAdj,
        return killPackageProcessesLSP(packageName, appId, userId, minOomAdj,
                false /* callerWillRestart */, true /* allowRestart */, true /* doit */,
                false /* callerWillRestart */, true /* allowRestart */, true /* doit */,
                false /* evenPersistent */, false /* setRemoved */, reasonCode,
                false /* evenPersistent */, false /* setRemoved */, false /* uninstalling */,
                subReason, reason);
                reasonCode, subReason, reason);
    }
    }


    @GuardedBy("mService")
    @GuardedBy("mService")
@@ -2785,9 +2785,10 @@ public final class ProcessList {
    @GuardedBy({"mService", "mProcLock"})
    @GuardedBy({"mService", "mProcLock"})
    boolean killPackageProcessesLSP(String packageName, int appId,
    boolean killPackageProcessesLSP(String packageName, int appId,
            int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
            int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
            boolean doit, boolean evenPersistent, boolean setRemoved, int reasonCode,
            boolean doit, boolean evenPersistent, boolean setRemoved, boolean uninstalling,
            int subReason, String reason) {
            int reasonCode, int subReason, String reason) {
        ArrayList<ProcessRecord> procs = new ArrayList<>();
        final PackageManagerInternal pm = mService.getPackageManagerInternal();
        final ArrayList<Pair<ProcessRecord, Boolean>> procs = new ArrayList<>();


        // Remove all processes this package may have touched: all with the
        // Remove all processes this package may have touched: all with the
        // same UID (except for the system or root user), and all whose name
        // same UID (except for the system or root user), and all whose name
@@ -2804,7 +2805,18 @@ public final class ProcessList {
                }
                }
                if (app.isRemoved()) {
                if (app.isRemoved()) {
                    if (doit) {
                    if (doit) {
                        procs.add(app);
                        boolean shouldAllowRestart = false;
                        if (!uninstalling && packageName != null) {
                            // This package has a dependency on the given package being stopped,
                            // while it's not being frozen nor uninstalled, allow to restart it.
                            shouldAllowRestart = !app.getPkgList().containsKey(packageName)
                                    && app.getPkgDeps() != null
                                    && app.getPkgDeps().contains(packageName)
                                    && app.info != null
                                    && !pm.isPackageFrozen(app.info.packageName, app.uid,
                                            app.userId);
                        }
                        procs.add(new Pair<>(app, shouldAllowRestart));
                    }
                    }
                    continue;
                    continue;
                }
                }
@@ -2819,6 +2831,8 @@ public final class ProcessList {
                    continue;
                    continue;
                }
                }


                boolean shouldAllowRestart = false;

                // If no package is specified, we call all processes under the
                // If no package is specified, we call all processes under the
                // give user id.
                // give user id.
                if (packageName == null) {
                if (packageName == null) {
@@ -2840,9 +2854,16 @@ public final class ProcessList {
                    if (userId != UserHandle.USER_ALL && app.userId != userId) {
                    if (userId != UserHandle.USER_ALL && app.userId != userId) {
                        continue;
                        continue;
                    }
                    }
                    if (!app.getPkgList().containsKey(packageName) && !isDep) {
                    final boolean isInPkgList = app.getPkgList().containsKey(packageName);
                    if (!isInPkgList && !isDep) {
                        continue;
                        continue;
                    }
                    }
                    if (!isInPkgList && isDep && !uninstalling && app.info != null
                            && !pm.isPackageFrozen(app.info.packageName, app.uid, app.userId)) {
                        // This package has a dependency on the given package being stopped,
                        // while it's not being frozen nor uninstalled, allow to restart it.
                        shouldAllowRestart = true;
                    }
                }
                }


                // Process has passed all conditions, kill it!
                // Process has passed all conditions, kill it!
@@ -2852,13 +2873,14 @@ public final class ProcessList {
                if (setRemoved) {
                if (setRemoved) {
                    app.setRemoved(true);
                    app.setRemoved(true);
                }
                }
                procs.add(app);
                procs.add(new Pair<>(app, shouldAllowRestart));
            }
            }
        }
        }


        int N = procs.size();
        int N = procs.size();
        for (int i=0; i<N; i++) {
        for (int i=0; i<N; i++) {
            removeProcessLocked(procs.get(i), callerWillRestart, allowRestart,
            final Pair<ProcessRecord, Boolean> proc = procs.get(i);
            removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second,
                     reasonCode, subReason, reason);
                     reasonCode, subReason, reason);
        }
        }
        killAppZygotesLocked(packageName, appId, userId, false /* force */);
        killAppZygotesLocked(packageName, appId, userId, false /* force */);
+7 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,13 @@
<configuration description="Runs Frameworks Services Tests.">
<configuration description="Runs Frameworks Services Tests.">
    <option name="test-suite-tag" value="apct" />
    <option name="test-suite-tag" value="apct" />
    <option name="test-suite-tag" value="apct-instrumentation" />
    <option name="test-suite-tag" value="apct-instrumentation" />

    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
        <option name="cleanup" value="true" />
        <option name="push-file" key="SimpleServiceTestApp3.apk"
                value="/data/local/tmp/cts/content/SimpleServiceTestApp3.apk" />
    </target_preparer>

    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
        <option name="cleanup-apks" value="true" />
        <option name="cleanup-apks" value="true" />
        <option name="install-arg" value="-t" />
        <option name="install-arg" value="-t" />
+88 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.server.am;
package com.android.server.am;


import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;


@@ -26,7 +27,9 @@ import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.os.IBinder;
import android.os.SystemClock;
import android.os.SystemClock;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import android.util.Log;
@@ -42,6 +45,8 @@ import org.junit.runner.RunWith;


import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
/**
 * Build/Install/Run:
 * Build/Install/Run:
@@ -69,6 +74,12 @@ public final class ServiceRestarterTest {
    private static final int ACTION_STOPPKG = 8;
    private static final int ACTION_STOPPKG = 8;
    private static final int ACTION_ALL = ACTION_START | ACTION_KILL | ACTION_WAIT | ACTION_STOPPKG;
    private static final int ACTION_ALL = ACTION_START | ACTION_KILL | ACTION_WAIT | ACTION_STOPPKG;


    private static final String LOCAL_APK_BASE_PATH = "/data/local/tmp/cts/content/";
    private static final String TEST_PACKAGE3_APK = "SimpleServiceTestApp3.apk";
    private static final String ACTION_SERVICE_WITH_DEP_PKG =
            "com.android.servicestests.apps.simpleservicetestapp.ACTION_SERVICE_WITH_DEP_PKG";
    private static final String EXTRA_TARGET_PACKAGE = "target_package";

    private Context mContext;
    private Context mContext;
    private Instrumentation mInstrumentation;
    private Instrumentation mInstrumentation;
    private int mTestPackage1Uid;
    private int mTestPackage1Uid;
@@ -199,6 +210,83 @@ public final class ServiceRestarterTest {
        return res;
        return res;
    }
    }


    @Test
    public void testServiceWithDepPkgStopped() throws Exception {
        final CountDownLatch[] latchHolder = new CountDownLatch[1];
        final ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                latchHolder[0].countDown();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                latchHolder[0].countDown();
            }
        };

        final long timeout = 5_000;
        final long shortTimeout = 2_000;
        final Intent intent = new Intent(ACTION_SERVICE_WITH_DEP_PKG);
        final String testPkg = TEST_PACKAGE2_NAME;
        final String libPkg = TEST_PACKAGE3_NAME;
        final String apkPath = LOCAL_APK_BASE_PATH + TEST_PACKAGE3_APK;
        final ActivityManager am = mContext.getSystemService(ActivityManager.class);

        intent.setComponent(ComponentName.unflattenFromString(testPkg + "/" + TEST_SERVICE_NAME));
        intent.putExtra(EXTRA_TARGET_PACKAGE, libPkg);
        try {
            executeShellCmd("am service-restart-backoff disable " + testPkg);

            latchHolder[0] = new CountDownLatch(1);
            assertTrue("Unable to bind to test service in " + testPkg,
                    mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE));
            assertTrue("Timed out to bind service in " + testPkg,
                    latchHolder[0].await(timeout, TimeUnit.MILLISECONDS));

            Thread.sleep(shortTimeout);
            assertTrue(libPkg + " should be a dependency package of " + testPkg,
                    isPackageDependency(testPkg, libPkg));

            // Force-stop lib package, the test service should be restarted.
            latchHolder[0] = new CountDownLatch(2);
            am.forceStopPackage(libPkg);
            assertTrue("Test service in didn't restart in " + testPkg,
                    latchHolder[0].await(timeout, TimeUnit.MILLISECONDS));

            Thread.sleep(shortTimeout);

            // Re-install the lib package, the test service should be restarted.
            latchHolder[0] = new CountDownLatch(2);
            assertTrue("Unable to install package " + apkPath, installPackage(apkPath));
            assertTrue("Test service in didn't restart in " + testPkg,
                    latchHolder[0].await(timeout, TimeUnit.MILLISECONDS));

            Thread.sleep(shortTimeout);

            // Force-stop the service package, the test service should not be restarted.
            latchHolder[0] = new CountDownLatch(2);
            am.forceStopPackage(testPkg);
            assertFalse("Test service should not be restarted in " + testPkg,
                    latchHolder[0].await(timeout * 2, TimeUnit.MILLISECONDS));
        } finally {
            executeShellCmd("am service-restart-backoff enable " + testPkg);
            mContext.unbindService(conn);
            am.forceStopPackage(testPkg);
        }
    }

    private boolean isPackageDependency(String pkgName, String libPackage) throws Exception {
        final String output = SystemUtil.runShellCommand("dumpsys activity processes " + pkgName);
        final Matcher matcher = Pattern.compile("packageDependencies=\\{.*?\\b"
                + libPackage + "\\b.*?\\}").matcher(output);
        return matcher.find();
    }

    private boolean installPackage(String apkPath) throws Exception {
        return executeShellCmd("pm install -t " + apkPath).equals("Success\n");
    }

    private void startServiceAndWait(String pkgName, MyUidImportanceListener uidListener,
    private void startServiceAndWait(String pkgName, MyUidImportanceListener uidListener,
            long timeout) throws Exception {
            long timeout) throws Exception {
        final Intent intent = new Intent();
        final Intent intent = new Intent();
+1 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@
        package="com.android.servicestests.apps.simpleservicetestapp">
        package="com.android.servicestests.apps.simpleservicetestapp">


    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />


    <application>
    <application>
        <service android:name=".SimpleService"
        <service android:name=".SimpleService"
Loading