Loading services/core/java/com/android/server/am/ActiveServices.java +88 −20 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NA import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.annotation.UptimeMillisLong; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal; import android.app.ActivityThread; import android.app.ActivityThread; Loading Loading @@ -242,6 +243,12 @@ public final class ActiveServices { @GuardedBy("mAm") @GuardedBy("mAm") private final SparseArray<AppOpCallback> mFgsAppOpCallbacks = new SparseArray<>(); private final SparseArray<AppOpCallback> mFgsAppOpCallbacks = new SparseArray<>(); /** * The list of packages with the service restart backoff disabled. */ @GuardedBy("mAm") private final ArraySet<String> mRestartBackoffDisabledPackages = new ArraySet<>(); /** /** * For keeping ActiveForegroundApps retaining state while the screen is off. * For keeping ActiveForegroundApps retaining state while the screen is off. */ */ Loading Loading @@ -3298,17 +3305,19 @@ public final class ActiveServices { } } } } if (isServiceRestartBackoffEnabledLocked(r.packageName)) { r.nextRestartTime = now + r.restartDelay; r.nextRestartTime = now + r.restartDelay; // Make sure that we don't end up restarting a bunch of services // Make sure that we don't end up restarting a bunch of services // all at the same time. // all at the same time. boolean repeat; boolean repeat; final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN; do { do { repeat = false; repeat = false; final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN; for (int i = mRestartingServices.size() - 1; i >= 0; i--) { for (int i = mRestartingServices.size() - 1; i >= 0; i--) { ServiceRecord r2 = mRestartingServices.get(i); final ServiceRecord r2 = mRestartingServices.get(i); if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime-restartTimeBetween) if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime - restartTimeBetween) && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) { && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) { r.nextRestartTime = r2.nextRestartTime + restartTimeBetween; r.nextRestartTime = r2.nextRestartTime + restartTimeBetween; r.restartDelay = r.nextRestartTime - now; r.restartDelay = r.nextRestartTime - now; Loading @@ -3317,6 +3326,11 @@ public final class ActiveServices { } } } } } while (repeat); } while (repeat); } else { // It's been forced to ignore the restart backoff, fix the delay here. r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION; r.nextRestartTime = now + r.restartDelay; } } else { } else { // Persistent processes are immediately restarted, so there is no // Persistent processes are immediately restarted, so there is no Loading @@ -3336,15 +3350,22 @@ public final class ActiveServices { cancelForegroundNotificationLocked(r); cancelForegroundNotificationLocked(r); performScheduleRestartLocked(r, "Scheduling", reason, SystemClock.uptimeMillis()); return true; } @VisibleForTesting @GuardedBy("mAm") void performScheduleRestartLocked(ServiceRecord r, @NonNull String scheduling, @NonNull String reason, @UptimeMillisLong long now) { mAm.mHandler.removeCallbacks(r.restarter); mAm.mHandler.removeCallbacks(r.restarter); mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime); mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime); r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; r.nextRestartTime = now + r.restartDelay; Slog.w(TAG, "Scheduling restart of crashed service " Slog.w(TAG, scheduling + " restart of crashed service " + r.shortInstanceName + " in " + r.restartDelay + "ms for " + reason); + r.shortInstanceName + " in " + r.restartDelay + "ms for " + reason); EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, r.userId, r.shortInstanceName, r.restartDelay); r.userId, r.shortInstanceName, r.restartDelay); return true; } } final void performServiceRestartLocked(ServiceRecord r) { final void performServiceRestartLocked(ServiceRecord r) { Loading Loading @@ -3409,6 +3430,52 @@ public final class ActiveServices { } } } } /** * Toggle service restart backoff policy, used by {@link ActivityManagerShellCommand}. */ @GuardedBy("mAm") void setServiceRestartBackoffEnabledLocked(@NonNull String packageName, boolean enable, @NonNull String reason) { if (!enable) { if (mRestartBackoffDisabledPackages.contains(packageName)) { // Already disabled, do nothing. return; } mRestartBackoffDisabledPackages.add(packageName); final long now = SystemClock.uptimeMillis(); for (int i = 0, size = mRestartingServices.size(); i < size; i++) { final ServiceRecord r = mRestartingServices.get(i); if (TextUtils.equals(r.packageName, packageName)) { final long remaining = r.nextRestartTime - now; if (remaining > mAm.mConstants.SERVICE_RESTART_DURATION) { r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION; r.nextRestartTime = now + r.restartDelay; performScheduleRestartLocked(r, "Rescheduling", reason, now); } } } } else { removeServiceRestartBackoffEnabledLocked(packageName); // For the simplicity, we are not going to reschedule its pending restarts // when we turn the backoff policy back on. } } @GuardedBy("mAm") private void removeServiceRestartBackoffEnabledLocked(@NonNull String packageName) { mRestartBackoffDisabledPackages.remove(packageName); } /** * @return {@code false} if the given package has been disable from enforcing the service * restart backoff policy, used by {@link ActivityManagerShellCommand}. */ @GuardedBy("mAm") boolean isServiceRestartBackoffEnabledLocked(@NonNull String packageName) { return !mRestartBackoffDisabledPackages.contains(packageName); } private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen, boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen, boolean enqueueOomAdj) boolean enqueueOomAdj) Loading Loading @@ -4457,6 +4524,7 @@ public final class ActiveServices { mPendingBringups.removeAt(i); mPendingBringups.removeAt(i); } } } } removeServiceRestartBackoffEnabledLocked(packageName); } } void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { Loading services/core/java/com/android/server/am/ActivityManagerService.java +20 −0 Original line number Original line Diff line number Diff line Loading @@ -8395,6 +8395,26 @@ public class ActivityManagerService extends IActivityManager.Stub } } } } /** * Toggle service restart backoff policy, used by {@link ActivityManagerShellCommand}. */ void setServiceRestartBackoffEnabled(@NonNull String packageName, boolean enable, @NonNull String reason) { synchronized (this) { mServices.setServiceRestartBackoffEnabledLocked(packageName, enable, reason); } } /** * @return {@code false} if the given package has been disable from enforcing the service * restart backoff policy, used by {@link ActivityManagerShellCommand}. */ boolean isServiceRestartBackoffEnabled(@NonNull String packageName) { synchronized (this) { return mServices.isServiceRestartBackoffEnabledLocked(packageName); } } @Override @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, FileDescriptor err, String[] args, ShellCallback callback, Loading services/core/java/com/android/server/am/ActivityManagerShellCommand.java +29 −0 Original line number Original line Diff line number Diff line Loading @@ -318,6 +318,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runRefreshSettingsCache(); return runRefreshSettingsCache(); case "memory-factor": case "memory-factor": return runMemoryFactor(pw); return runMemoryFactor(pw); case "service-restart-backoff": return runServiceRestartBackoff(pw); default: default: return handleDefaultCommands(cmd); return handleDefaultCommands(cmd); } } Loading Loading @@ -3095,6 +3097,28 @@ final class ActivityManagerShellCommand extends ShellCommand { } } } } private int runServiceRestartBackoff(PrintWriter pw) throws RemoteException { mInternal.enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT, "runServiceRestartBackoff()"); final String opt = getNextArgRequired(); switch (opt) { case "enable": mInternal.setServiceRestartBackoffEnabled(getNextArgRequired(), true, "shell"); return 0; case "disable": mInternal.setServiceRestartBackoffEnabled(getNextArgRequired(), false, "shell"); return 0; case "show": pw.println(mInternal.isServiceRestartBackoffEnabled(getNextArgRequired()) ? "enabled" : "disabled"); return 0; default: getErrPrintWriter().println("Error: unknown command '" + opt + "'"); return -1; } } private Resources getResources(PrintWriter pw) throws RemoteException { private Resources getResources(PrintWriter pw) throws RemoteException { // system resources does not contain all the device configuration, construct it manually. // system resources does not contain all the device configuration, construct it manually. Configuration config = mInterface.getConfiguration(); Configuration config = mInterface.getConfiguration(); Loading Loading @@ -3418,6 +3442,11 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" Shows the existing memory pressure factor"); pw.println(" Shows the existing memory pressure factor"); pw.println(" reset"); pw.println(" reset"); pw.println(" Removes existing override for memory pressure factor"); pw.println(" Removes existing override for memory pressure factor"); pw.println(" service-restart-backoff <COMMAND> [...]: sub-commands to toggle service restart backoff policy."); pw.println(" enable|disable <PACKAGE_NAME>"); pw.println(" Toggles the restart backoff policy on/off for <PACKAGE_NAME>."); pw.println(" show <PACKAGE_NAME>"); pw.println(" Shows the restart backoff policy state for <PACKAGE_NAME>."); pw.println(); pw.println(); Intent.printIntentArgsHelp(pw, ""); Intent.printIntentArgsHelp(pw, ""); } } Loading services/tests/servicestests/AndroidManifest.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -91,6 +91,7 @@ <uses-permission android:name="android.permission.VIBRATE_ALWAYS_ON"/> <uses-permission android:name="android.permission.VIBRATE_ALWAYS_ON"/> <uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/> <uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/> <uses-permission android:name="android.permission.READ_PROJECTION_STATE"/> <uses-permission android:name="android.permission.READ_PROJECTION_STATE"/> <uses-permission android:name="android.permission.KILL_UID"/> <!-- Uses API introduced in O (26) --> <!-- Uses API introduced in O (26) --> <uses-sdk android:minSdkVersion="1" <uses-sdk android:minSdkVersion="1" Loading services/tests/servicestests/AndroidTest.xml +3 −1 Original line number Original line Diff line number Diff line Loading @@ -23,7 +23,9 @@ <option name="test-file-name" value="JobTestApp.apk" /> <option name="test-file-name" value="JobTestApp.apk" /> <option name="test-file-name" value="ConnTestApp.apk" /> <option name="test-file-name" value="ConnTestApp.apk" /> <option name="test-file-name" value="SuspendTestApp.apk" /> <option name="test-file-name" value="SuspendTestApp.apk" /> <option name="test-file-name" value="SimpleServiceTestApp.apk" /> <option name="test-file-name" value="SimpleServiceTestApp1.apk" /> <option name="test-file-name" value="SimpleServiceTestApp2.apk" /> <option name="test-file-name" value="SimpleServiceTestApp3.apk" /> </target_preparer> </target_preparer> <option name="test-tag" value="FrameworksServicesTests" /> <option name="test-tag" value="FrameworksServicesTests" /> Loading Loading
services/core/java/com/android/server/am/ActiveServices.java +88 −20 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NA import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.annotation.UptimeMillisLong; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal; import android.app.ActivityThread; import android.app.ActivityThread; Loading Loading @@ -242,6 +243,12 @@ public final class ActiveServices { @GuardedBy("mAm") @GuardedBy("mAm") private final SparseArray<AppOpCallback> mFgsAppOpCallbacks = new SparseArray<>(); private final SparseArray<AppOpCallback> mFgsAppOpCallbacks = new SparseArray<>(); /** * The list of packages with the service restart backoff disabled. */ @GuardedBy("mAm") private final ArraySet<String> mRestartBackoffDisabledPackages = new ArraySet<>(); /** /** * For keeping ActiveForegroundApps retaining state while the screen is off. * For keeping ActiveForegroundApps retaining state while the screen is off. */ */ Loading Loading @@ -3298,17 +3305,19 @@ public final class ActiveServices { } } } } if (isServiceRestartBackoffEnabledLocked(r.packageName)) { r.nextRestartTime = now + r.restartDelay; r.nextRestartTime = now + r.restartDelay; // Make sure that we don't end up restarting a bunch of services // Make sure that we don't end up restarting a bunch of services // all at the same time. // all at the same time. boolean repeat; boolean repeat; final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN; do { do { repeat = false; repeat = false; final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN; for (int i = mRestartingServices.size() - 1; i >= 0; i--) { for (int i = mRestartingServices.size() - 1; i >= 0; i--) { ServiceRecord r2 = mRestartingServices.get(i); final ServiceRecord r2 = mRestartingServices.get(i); if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime-restartTimeBetween) if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime - restartTimeBetween) && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) { && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) { r.nextRestartTime = r2.nextRestartTime + restartTimeBetween; r.nextRestartTime = r2.nextRestartTime + restartTimeBetween; r.restartDelay = r.nextRestartTime - now; r.restartDelay = r.nextRestartTime - now; Loading @@ -3317,6 +3326,11 @@ public final class ActiveServices { } } } } } while (repeat); } while (repeat); } else { // It's been forced to ignore the restart backoff, fix the delay here. r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION; r.nextRestartTime = now + r.restartDelay; } } else { } else { // Persistent processes are immediately restarted, so there is no // Persistent processes are immediately restarted, so there is no Loading @@ -3336,15 +3350,22 @@ public final class ActiveServices { cancelForegroundNotificationLocked(r); cancelForegroundNotificationLocked(r); performScheduleRestartLocked(r, "Scheduling", reason, SystemClock.uptimeMillis()); return true; } @VisibleForTesting @GuardedBy("mAm") void performScheduleRestartLocked(ServiceRecord r, @NonNull String scheduling, @NonNull String reason, @UptimeMillisLong long now) { mAm.mHandler.removeCallbacks(r.restarter); mAm.mHandler.removeCallbacks(r.restarter); mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime); mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime); r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; r.nextRestartTime = now + r.restartDelay; Slog.w(TAG, "Scheduling restart of crashed service " Slog.w(TAG, scheduling + " restart of crashed service " + r.shortInstanceName + " in " + r.restartDelay + "ms for " + reason); + r.shortInstanceName + " in " + r.restartDelay + "ms for " + reason); EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, r.userId, r.shortInstanceName, r.restartDelay); r.userId, r.shortInstanceName, r.restartDelay); return true; } } final void performServiceRestartLocked(ServiceRecord r) { final void performServiceRestartLocked(ServiceRecord r) { Loading Loading @@ -3409,6 +3430,52 @@ public final class ActiveServices { } } } } /** * Toggle service restart backoff policy, used by {@link ActivityManagerShellCommand}. */ @GuardedBy("mAm") void setServiceRestartBackoffEnabledLocked(@NonNull String packageName, boolean enable, @NonNull String reason) { if (!enable) { if (mRestartBackoffDisabledPackages.contains(packageName)) { // Already disabled, do nothing. return; } mRestartBackoffDisabledPackages.add(packageName); final long now = SystemClock.uptimeMillis(); for (int i = 0, size = mRestartingServices.size(); i < size; i++) { final ServiceRecord r = mRestartingServices.get(i); if (TextUtils.equals(r.packageName, packageName)) { final long remaining = r.nextRestartTime - now; if (remaining > mAm.mConstants.SERVICE_RESTART_DURATION) { r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION; r.nextRestartTime = now + r.restartDelay; performScheduleRestartLocked(r, "Rescheduling", reason, now); } } } } else { removeServiceRestartBackoffEnabledLocked(packageName); // For the simplicity, we are not going to reschedule its pending restarts // when we turn the backoff policy back on. } } @GuardedBy("mAm") private void removeServiceRestartBackoffEnabledLocked(@NonNull String packageName) { mRestartBackoffDisabledPackages.remove(packageName); } /** * @return {@code false} if the given package has been disable from enforcing the service * restart backoff policy, used by {@link ActivityManagerShellCommand}. */ @GuardedBy("mAm") boolean isServiceRestartBackoffEnabledLocked(@NonNull String packageName) { return !mRestartBackoffDisabledPackages.contains(packageName); } private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen, boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen, boolean enqueueOomAdj) boolean enqueueOomAdj) Loading Loading @@ -4457,6 +4524,7 @@ public final class ActiveServices { mPendingBringups.removeAt(i); mPendingBringups.removeAt(i); } } } } removeServiceRestartBackoffEnabledLocked(packageName); } } void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { Loading
services/core/java/com/android/server/am/ActivityManagerService.java +20 −0 Original line number Original line Diff line number Diff line Loading @@ -8395,6 +8395,26 @@ public class ActivityManagerService extends IActivityManager.Stub } } } } /** * Toggle service restart backoff policy, used by {@link ActivityManagerShellCommand}. */ void setServiceRestartBackoffEnabled(@NonNull String packageName, boolean enable, @NonNull String reason) { synchronized (this) { mServices.setServiceRestartBackoffEnabledLocked(packageName, enable, reason); } } /** * @return {@code false} if the given package has been disable from enforcing the service * restart backoff policy, used by {@link ActivityManagerShellCommand}. */ boolean isServiceRestartBackoffEnabled(@NonNull String packageName) { synchronized (this) { return mServices.isServiceRestartBackoffEnabledLocked(packageName); } } @Override @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, FileDescriptor err, String[] args, ShellCallback callback, Loading
services/core/java/com/android/server/am/ActivityManagerShellCommand.java +29 −0 Original line number Original line Diff line number Diff line Loading @@ -318,6 +318,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runRefreshSettingsCache(); return runRefreshSettingsCache(); case "memory-factor": case "memory-factor": return runMemoryFactor(pw); return runMemoryFactor(pw); case "service-restart-backoff": return runServiceRestartBackoff(pw); default: default: return handleDefaultCommands(cmd); return handleDefaultCommands(cmd); } } Loading Loading @@ -3095,6 +3097,28 @@ final class ActivityManagerShellCommand extends ShellCommand { } } } } private int runServiceRestartBackoff(PrintWriter pw) throws RemoteException { mInternal.enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT, "runServiceRestartBackoff()"); final String opt = getNextArgRequired(); switch (opt) { case "enable": mInternal.setServiceRestartBackoffEnabled(getNextArgRequired(), true, "shell"); return 0; case "disable": mInternal.setServiceRestartBackoffEnabled(getNextArgRequired(), false, "shell"); return 0; case "show": pw.println(mInternal.isServiceRestartBackoffEnabled(getNextArgRequired()) ? "enabled" : "disabled"); return 0; default: getErrPrintWriter().println("Error: unknown command '" + opt + "'"); return -1; } } private Resources getResources(PrintWriter pw) throws RemoteException { private Resources getResources(PrintWriter pw) throws RemoteException { // system resources does not contain all the device configuration, construct it manually. // system resources does not contain all the device configuration, construct it manually. Configuration config = mInterface.getConfiguration(); Configuration config = mInterface.getConfiguration(); Loading Loading @@ -3418,6 +3442,11 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" Shows the existing memory pressure factor"); pw.println(" Shows the existing memory pressure factor"); pw.println(" reset"); pw.println(" reset"); pw.println(" Removes existing override for memory pressure factor"); pw.println(" Removes existing override for memory pressure factor"); pw.println(" service-restart-backoff <COMMAND> [...]: sub-commands to toggle service restart backoff policy."); pw.println(" enable|disable <PACKAGE_NAME>"); pw.println(" Toggles the restart backoff policy on/off for <PACKAGE_NAME>."); pw.println(" show <PACKAGE_NAME>"); pw.println(" Shows the restart backoff policy state for <PACKAGE_NAME>."); pw.println(); pw.println(); Intent.printIntentArgsHelp(pw, ""); Intent.printIntentArgsHelp(pw, ""); } } Loading
services/tests/servicestests/AndroidManifest.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -91,6 +91,7 @@ <uses-permission android:name="android.permission.VIBRATE_ALWAYS_ON"/> <uses-permission android:name="android.permission.VIBRATE_ALWAYS_ON"/> <uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/> <uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/> <uses-permission android:name="android.permission.READ_PROJECTION_STATE"/> <uses-permission android:name="android.permission.READ_PROJECTION_STATE"/> <uses-permission android:name="android.permission.KILL_UID"/> <!-- Uses API introduced in O (26) --> <!-- Uses API introduced in O (26) --> <uses-sdk android:minSdkVersion="1" <uses-sdk android:minSdkVersion="1" Loading
services/tests/servicestests/AndroidTest.xml +3 −1 Original line number Original line Diff line number Diff line Loading @@ -23,7 +23,9 @@ <option name="test-file-name" value="JobTestApp.apk" /> <option name="test-file-name" value="JobTestApp.apk" /> <option name="test-file-name" value="ConnTestApp.apk" /> <option name="test-file-name" value="ConnTestApp.apk" /> <option name="test-file-name" value="SuspendTestApp.apk" /> <option name="test-file-name" value="SuspendTestApp.apk" /> <option name="test-file-name" value="SimpleServiceTestApp.apk" /> <option name="test-file-name" value="SimpleServiceTestApp1.apk" /> <option name="test-file-name" value="SimpleServiceTestApp2.apk" /> <option name="test-file-name" value="SimpleServiceTestApp3.apk" /> </target_preparer> </target_preparer> <option name="test-tag" value="FrameworksServicesTests" /> <option name="test-tag" value="FrameworksServicesTests" /> Loading