Loading services/core/java/com/android/server/am/ActivityManagerService.java +3 −1 Original line number Diff line number Diff line Loading @@ -4299,7 +4299,7 @@ public class ActivityManagerService extends IActivityManager.Stub didSomething |= mProcessList.killPackageProcessesLSP(packageName, appId, userId, ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit, evenPersistent, true /* setRemoved */, evenPersistent, true /* setRemoved */, uninstalling, packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED : ApplicationExitInfo.REASON_USER_REQUESTED, ApplicationExitInfo.SUBREASON_UNKNOWN, Loading Loading @@ -7382,6 +7382,7 @@ public class ActivityManagerService extends IActivityManager.Stub ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */, true /* callerWillRestart */, true /* doit */, true /* evenPersistent */, false /* setRemoved */, false /* uninstalling */, ApplicationExitInfo.REASON_OTHER, ApplicationExitInfo.SUBREASON_KILL_UID, reason != null ? reason : "kill uid"); Loading @@ -7403,6 +7404,7 @@ public class ActivityManagerService extends IActivityManager.Stub ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */, true /* callerWillRestart */, true /* doit */, true /* evenPersistent */, false /* setRemoved */, false /* uninstalling */, ApplicationExitInfo.REASON_PERMISSION_CHANGE, ApplicationExitInfo.SUBREASON_UNKNOWN, reason != null ? reason : "kill uid"); Loading services/core/java/com/android/server/am/ProcessList.java +31 −10 Original line number Diff line number Diff line Loading @@ -135,7 +135,6 @@ import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService.ProcessChangeItem; import com.android.server.compat.PlatformCompat; import com.android.server.pm.dex.DexManager; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.wm.ActivityServiceConnectionsHolder; import com.android.server.wm.WindowManagerService; Loading Loading @@ -2794,8 +2793,8 @@ public final class ProcessList { int reasonCode, int subReason, String reason) { return killPackageProcessesLSP(packageName, appId, userId, minOomAdj, false /* callerWillRestart */, true /* allowRestart */, true /* doit */, false /* evenPersistent */, false /* setRemoved */, reasonCode, subReason, reason); false /* evenPersistent */, false /* setRemoved */, false /* uninstalling */, reasonCode, subReason, reason); } @GuardedBy("mService") Loading Loading @@ -2828,9 +2827,10 @@ public final class ProcessList { @GuardedBy({"mService", "mProcLock"}) boolean killPackageProcessesLSP(String packageName, int appId, int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit, boolean evenPersistent, boolean setRemoved, int reasonCode, int subReason, String reason) { ArrayList<ProcessRecord> procs = new ArrayList<>(); boolean doit, boolean evenPersistent, boolean setRemoved, boolean uninstalling, int reasonCode, int subReason, String reason) { final PackageManagerInternal pm = mService.getPackageManagerInternal(); final ArrayList<Pair<ProcessRecord, Boolean>> procs = new ArrayList<>(); // Remove all processes this package may have touched: all with the // same UID (except for the system or root user), and all whose name Loading @@ -2847,7 +2847,18 @@ public final class ProcessList { } if (app.isRemoved()) { 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; } Loading @@ -2862,6 +2873,8 @@ public final class ProcessList { continue; } boolean shouldAllowRestart = false; // If no package is specified, we call all processes under the // give user id. if (packageName == null) { Loading @@ -2883,9 +2896,16 @@ public final class ProcessList { if (userId != UserHandle.USER_ALL && app.userId != userId) { continue; } if (!app.getPkgList().containsKey(packageName) && !isDep) { final boolean isInPkgList = app.getPkgList().containsKey(packageName); if (!isInPkgList && !isDep) { 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! Loading @@ -2895,13 +2915,14 @@ public final class ProcessList { if (setRemoved) { app.setRemoved(true); } procs.add(app); procs.add(new Pair<>(app, shouldAllowRestart)); } } int N = procs.size(); 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); } killAppZygotesLocked(packageName, appId, userId, false /* force */); Loading services/tests/servicestests/AndroidTest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,13 @@ <configuration description="Runs Frameworks Services Tests."> <option name="test-suite-tag" value="apct" /> <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"> <option name="cleanup-apks" value="true" /> <option name="install-arg" value="-t" /> Loading services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java +88 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE; import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; Loading @@ -30,7 +31,9 @@ import android.app.Instrumentation; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.os.IBinder; import android.os.SystemClock; import android.provider.DeviceConfig; import android.provider.Settings; Loading @@ -50,6 +53,8 @@ import org.junit.runner.RunWith; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Build/Install/Run: Loading Loading @@ -83,6 +88,12 @@ public final class ServiceRestarterTest { private static final int ACTION_STOPPKG = 8; 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 SettingsSession<String> mAMConstantsSettings; private DeviceConfigSession<String> mExtraDelaysDeviceConfig; private DeviceConfigSession<Boolean> mEnableExtraDelaysDeviceConfig; Loading Loading @@ -348,6 +359,83 @@ public final class ServiceRestarterTest { 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, long timeout) throws Exception { final Intent intent = new Intent(); Loading services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package="com.android.servicestests.apps.simpleservicetestapp"> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <application> <service android:name=".SimpleService" Loading Loading
services/core/java/com/android/server/am/ActivityManagerService.java +3 −1 Original line number Diff line number Diff line Loading @@ -4299,7 +4299,7 @@ public class ActivityManagerService extends IActivityManager.Stub didSomething |= mProcessList.killPackageProcessesLSP(packageName, appId, userId, ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit, evenPersistent, true /* setRemoved */, evenPersistent, true /* setRemoved */, uninstalling, packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED : ApplicationExitInfo.REASON_USER_REQUESTED, ApplicationExitInfo.SUBREASON_UNKNOWN, Loading Loading @@ -7382,6 +7382,7 @@ public class ActivityManagerService extends IActivityManager.Stub ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */, true /* callerWillRestart */, true /* doit */, true /* evenPersistent */, false /* setRemoved */, false /* uninstalling */, ApplicationExitInfo.REASON_OTHER, ApplicationExitInfo.SUBREASON_KILL_UID, reason != null ? reason : "kill uid"); Loading @@ -7403,6 +7404,7 @@ public class ActivityManagerService extends IActivityManager.Stub ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */, true /* callerWillRestart */, true /* doit */, true /* evenPersistent */, false /* setRemoved */, false /* uninstalling */, ApplicationExitInfo.REASON_PERMISSION_CHANGE, ApplicationExitInfo.SUBREASON_UNKNOWN, reason != null ? reason : "kill uid"); Loading
services/core/java/com/android/server/am/ProcessList.java +31 −10 Original line number Diff line number Diff line Loading @@ -135,7 +135,6 @@ import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService.ProcessChangeItem; import com.android.server.compat.PlatformCompat; import com.android.server.pm.dex.DexManager; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.wm.ActivityServiceConnectionsHolder; import com.android.server.wm.WindowManagerService; Loading Loading @@ -2794,8 +2793,8 @@ public final class ProcessList { int reasonCode, int subReason, String reason) { return killPackageProcessesLSP(packageName, appId, userId, minOomAdj, false /* callerWillRestart */, true /* allowRestart */, true /* doit */, false /* evenPersistent */, false /* setRemoved */, reasonCode, subReason, reason); false /* evenPersistent */, false /* setRemoved */, false /* uninstalling */, reasonCode, subReason, reason); } @GuardedBy("mService") Loading Loading @@ -2828,9 +2827,10 @@ public final class ProcessList { @GuardedBy({"mService", "mProcLock"}) boolean killPackageProcessesLSP(String packageName, int appId, int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit, boolean evenPersistent, boolean setRemoved, int reasonCode, int subReason, String reason) { ArrayList<ProcessRecord> procs = new ArrayList<>(); boolean doit, boolean evenPersistent, boolean setRemoved, boolean uninstalling, int reasonCode, int subReason, String reason) { final PackageManagerInternal pm = mService.getPackageManagerInternal(); final ArrayList<Pair<ProcessRecord, Boolean>> procs = new ArrayList<>(); // Remove all processes this package may have touched: all with the // same UID (except for the system or root user), and all whose name Loading @@ -2847,7 +2847,18 @@ public final class ProcessList { } if (app.isRemoved()) { 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; } Loading @@ -2862,6 +2873,8 @@ public final class ProcessList { continue; } boolean shouldAllowRestart = false; // If no package is specified, we call all processes under the // give user id. if (packageName == null) { Loading @@ -2883,9 +2896,16 @@ public final class ProcessList { if (userId != UserHandle.USER_ALL && app.userId != userId) { continue; } if (!app.getPkgList().containsKey(packageName) && !isDep) { final boolean isInPkgList = app.getPkgList().containsKey(packageName); if (!isInPkgList && !isDep) { 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! Loading @@ -2895,13 +2915,14 @@ public final class ProcessList { if (setRemoved) { app.setRemoved(true); } procs.add(app); procs.add(new Pair<>(app, shouldAllowRestart)); } } int N = procs.size(); 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); } killAppZygotesLocked(packageName, appId, userId, false /* force */); Loading
services/tests/servicestests/AndroidTest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,13 @@ <configuration description="Runs Frameworks Services Tests."> <option name="test-suite-tag" value="apct" /> <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"> <option name="cleanup-apks" value="true" /> <option name="install-arg" value="-t" /> Loading
services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java +88 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE; import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; Loading @@ -30,7 +31,9 @@ import android.app.Instrumentation; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.os.IBinder; import android.os.SystemClock; import android.provider.DeviceConfig; import android.provider.Settings; Loading @@ -50,6 +53,8 @@ import org.junit.runner.RunWith; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Build/Install/Run: Loading Loading @@ -83,6 +88,12 @@ public final class ServiceRestarterTest { private static final int ACTION_STOPPKG = 8; 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 SettingsSession<String> mAMConstantsSettings; private DeviceConfigSession<String> mExtraDelaysDeviceConfig; private DeviceConfigSession<Boolean> mEnableExtraDelaysDeviceConfig; Loading Loading @@ -348,6 +359,83 @@ public final class ServiceRestarterTest { 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, long timeout) throws Exception { final Intent intent = new Intent(); Loading
services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package="com.android.servicestests.apps.simpleservicetestapp"> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <application> <service android:name=".SimpleService" Loading