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

Commit 65645292 authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Add an am command to disable service restart backoff policy." into sc-dev

parents 88d37222 f45997c0
Loading
Loading
Loading
Loading
+88 −20
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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.
     */
     */
@@ -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;
@@ -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
@@ -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) {
@@ -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)
@@ -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) {
+20 −0
Original line number Original line Diff line number Diff line
@@ -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,
+29 −0
Original line number Original line Diff line number Diff line
@@ -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);
            }
            }
@@ -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();
@@ -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, "");
        }
        }
+1 −0
Original line number Original line Diff line number Diff line
@@ -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"
+3 −1
Original line number Original line Diff line number Diff line
@@ -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