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

Commit e428a7f6 authored by Craig Mautner's avatar Craig Mautner
Browse files

Allow for more than one home app.

Having a single mHomeProcess in ActivityManagerService ignores the
possibility of multiple processes serving as home. Particularly when
we have a home activity that only serves to launch the true home
activity.

Fixes bug b10296766

Change-Id: I9e5c9c955c64f4b3df856b6bc66d6a0d93f85aab
parent 80f7ec06
Loading
Loading
Loading
Loading
+38 −27
Original line number Diff line number Diff line
@@ -21,12 +21,12 @@ import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import android.app.AppOpsManager;
import android.appwidget.AppWidgetManager;
import android.util.ArrayMap;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
@@ -52,6 +52,7 @@ import com.android.server.pm.UserManagerService;
import com.android.server.wm.AppTransition;
import com.android.server.wm.StackBox;
import com.android.server.wm.WindowManagerService;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -154,6 +155,7 @@ import android.os.UpdateLock;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.format.Time;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Log;
@@ -536,7 +538,7 @@ public final class ActivityManagerService extends ActivityManagerNative
     * This is the process holding what we currently consider to be
     * the "home" activity.
     */
    ProcessRecord mHomeProcess;
    ArraySet<ProcessRecord> mHomeProcess = new ArraySet<ProcessRecord>();
    /**
     * This is the process holding the activity the user last visited that
@@ -8951,11 +8953,11 @@ public final class ActivityManagerService extends ActivityManagerNative
        // replaced by a third-party app, clear the package preferred activities from packages
        // with a home activity running in the process to prevent a repeatedly crashing app
        // from blocking the user to manually clear the list.
        if (app == mHomeProcess && mHomeProcess.activities.size() > 0
                    && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
            Iterator<ActivityRecord> it = mHomeProcess.activities.iterator();
            while (it.hasNext()) {
                ActivityRecord r = it.next();
        final ArrayList<ActivityRecord> activities = app.activities;
        if (mHomeProcess.contains(app) && activities.size() > 0
                    && (app.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                final ActivityRecord r = activities.get(activityNdx);
                if (r.isHomeActivity()) {
                    Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
                    try {
@@ -10230,13 +10232,20 @@ public final class ActivityManagerService extends ActivityManagerNative
                pw.print("  mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray));
            }
        }
        if (mHomeProcess != null && (dumpPackage == null
                || mHomeProcess.pkgList.containsKey(dumpPackage))) {
        if (!mHomeProcess.isEmpty()) {
            final int size = mHomeProcess.size();
            ProcessRecord[] processes = new ProcessRecord[size];
            mHomeProcess.toArray(processes);
            for (int processNdx = 0; processNdx < size; ++processNdx) {
                final ProcessRecord app = processes[processNdx];
                if (dumpPackage == null || app.pkgList.containsKey(dumpPackage)) {
                    if (needSep) {
                        pw.println();
                        needSep = false;
                    }
            pw.println("  mHomeProcess: " + mHomeProcess);
                    pw.println("  mHomeProcess[" + processNdx + "]: " + app);
                }
            }
        }
        if (mPreviousProcess != null && (dumpPackage == null
                || mPreviousProcess.pkgList.containsKey(dumpPackage))) {
@@ -11859,6 +11868,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
        mHomeProcess.remove(app);
        // If the caller is restarting this app, then leave it in its
        // current lists and let the caller take care of it.
        if (restarting) {
@@ -11888,8 +11899,8 @@ public final class ActivityManagerService extends ActivityManagerNative
                "Clean-up removing on hold: " + app);
        mProcessesOnHold.remove(app);
        if (app == mHomeProcess) {
            mHomeProcess = null;
        if (mHomeProcess.contains(app)) {
            mHomeProcess.remove(app);
        }
        if (app == mPreviousProcess) {
            mPreviousProcess = null;
@@ -13815,7 +13826,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            }
        }
        if (app == mHomeProcess) {
        if (mHomeProcess.contains(app)) {
            if (adj > ProcessList.HOME_APP_ADJ) {
                // This process is hosting what we currently consider to be the
                // home app, so we don't want to let it go into the background.
@@ -13882,7 +13893,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
                    procState = ActivityManager.PROCESS_STATE_SERVICE;
                }
                if (app.hasShownUi && app != mHomeProcess) {
                if (app.hasShownUi && !mHomeProcess.contains(app)) {
                    // If this process has shown some UI, let it immediately
                    // go to the LRU list because it may be pretty heavy with
                    // UI stuff.  We'll tag it with a label just to help
@@ -13945,7 +13956,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                        if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                            // Not doing bind OOM management, so treat
                            // this guy more like a started service.
                            if (app.hasShownUi && app != mHomeProcess) {
                            if (app.hasShownUi && !mHomeProcess.contains(app)) {
                                // If this process has shown some UI, let it immediately
                                // go to the LRU list because it may be pretty heavy with
                                // UI stuff.  We'll tag it with a label just to help
@@ -14000,7 +14011,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                            // about letting this process get into the LRU
                            // list to be killed and restarted if needed for
                            // memory.
                            if (app.hasShownUi && app != mHomeProcess
                            if (app.hasShownUi && !mHomeProcess.contains(app)
                                    && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                adjType = "cch-bound-ui-services";
                            } else {
@@ -14114,7 +14125,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                    clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                }
                if (adj > clientAdj) {
                    if (app.hasShownUi && app != mHomeProcess
                    if (app.hasShownUi && !mHomeProcess.contains(app)
                            && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                        app.adjType = "cch-ui-provider";
                    } else {
@@ -14974,7 +14985,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                            // to be good enough at this point that destroying
                            // activities causes more harm than good.
                            if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
                                    && app != mHomeProcess && app != mPreviousProcess) {
                                    && !mHomeProcess.contains(app) && app != mPreviousProcess) {
                                // Need to do this on its own message because the stack may not
                                // be in a consistent state at this point.
                                // For these apps we will also finish their activities
+1 −1
Original line number Diff line number Diff line
@@ -2246,7 +2246,7 @@ final class ActivityStack {
                if (r.state == ActivityState.RESUMED
                        || r.state == ActivityState.PAUSING
                        || r.state == ActivityState.PAUSED) {
                    if (!r.isHomeActivity() || mService.mHomeProcess != r.app) {
                    if (!r.isHomeActivity() || !mService.mHomeProcess.contains(r.app)) {
                        Slog.w(TAG, "  Force finishing activity "
                                + r.intent.getComponent().flattenToShortString());
                        finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
+2 −2
Original line number Diff line number Diff line
@@ -905,7 +905,7 @@ public final class ActivityStackSupervisor {
                        r.task.taskId, r.shortComponentName);
            }
            if (r.isHomeActivity() && r.isNotResolverActivity()) {
                mService.mHomeProcess = app;
                mService.mHomeProcess.add(app);
            }
            mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
            r.sleeping = false;
@@ -1946,7 +1946,7 @@ public final class ActivityStackSupervisor {
        // makes sense to.
        if (r.app != null && fgApp != null && r.app != fgApp
                && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
                && r.app != mService.mHomeProcess) {
                && !mService.mHomeProcess.contains(r.app)) {
            mService.mPreviousProcess = r.app;
            mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
        }