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

Commit e44dfe9b authored by Zimuzo Ezeozue's avatar Zimuzo Ezeozue Committed by Android (Google) Code Review
Browse files

Merge changes Ie694d39b,Iaa51d310

* changes:
  Enable wait for finish attach application
  Split attachApplication to more accurately identify app startup
parents 260eef69 f47d4602
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -505,6 +505,7 @@ public final class ActivityThread extends ClientTransactionHandler

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    static volatile Handler sMainThreadHandler;  // set once in main()
    private long mStartSeq; // Only accesssed from the main thread

    Bundle mCoreSettings = null;

@@ -6987,6 +6988,12 @@ public final class ActivityThread extends ClientTransactionHandler
                throw e.rethrowFromSystemServer();
            }
        }

        try {
            mgr.finishAttachApplication(mStartSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

    @UnsupportedAppUsage
@@ -7791,6 +7798,8 @@ public final class ActivityThread extends ClientTransactionHandler
        sCurrentActivityThread = this;
        mConfigurationController = new ConfigurationController(this);
        mSystemThread = system;
        mStartSeq = startSeq;

        if (!system) {
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
+3 −2
Original line number Diff line number Diff line
@@ -147,6 +147,7 @@ interface IActivityManager {
    oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map,
            boolean abortBroadcast, int flags);
    void attachApplication(in IApplicationThread app, long startSeq);
    void finishAttachApplication(long startSeq);
    List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
    @UnsupportedAppUsage
    void moveTaskToFront(in IApplicationThread caller, in String callingPackage, int task,
+27 −0
Original line number Diff line number Diff line
@@ -954,6 +954,20 @@ final class ActivityManagerConstants extends ContentObserver {
    public volatile long mShortFgsProcStateExtraWaitDuration =
            DEFAULT_SHORT_FGS_PROC_STATE_EXTRA_WAIT_DURATION;

    /**
     * If enabled, when starting an application, the system will wait for a
     * {@link ActivityManagerService#finishAttachApplication} from the app before scheduling
     * Broadcasts or Services to it.
     */
    private static final String KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION =
            "enable_wait_for_finish_attach_application";

    private static final boolean DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION = true;

    /** @see #KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION */
    public volatile boolean mEnableWaitForFinishAttachApplication =
            DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION;

    /**
     * If a "short service" doesn't finish within this after the timeout (
     * {@link #KEY_SHORT_FGS_TIMEOUT_DURATION}), then we'll declare an ANR.
@@ -1125,6 +1139,10 @@ final class ActivityManagerConstants extends ContentObserver {
                                break;
                            case KEY_TOP_TO_FGS_GRACE_DURATION:
                                updateTopToFgsGraceDuration();
                                break;
                            case KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION:
                                updateEnableWaitForFinishAttachApplication();
                                break;
                            default:
                                break;
                        }
@@ -1840,6 +1858,13 @@ final class ActivityManagerConstants extends ContentObserver {
                DEFAULT_SHORT_FGS_ANR_EXTRA_WAIT_DURATION);
    }

    private void updateEnableWaitForFinishAttachApplication() {
        mEnableWaitForFinishAttachApplication = DeviceConfig.getBoolean(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION,
                DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION);
    }

    @NeverCompile // Avoid size overhead of debugging code.
    void dump(PrintWriter pw) {
        pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
@@ -2027,5 +2052,7 @@ final class ActivityManagerConstants extends ContentObserver {
        pw.print("  CUR_TRIM_EMPTY_PROCESSES="); pw.println(CUR_TRIM_EMPTY_PROCESSES);
        pw.print("  CUR_TRIM_CACHED_PROCESSES="); pw.println(CUR_TRIM_CACHED_PROCESSES);
        pw.print("  OOMADJ_UPDATE_QUICK="); pw.println(OOMADJ_UPDATE_QUICK);
        pw.print("  ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION=");
        pw.println(mEnableWaitForFinishAttachApplication);
    }
}
+184 −124
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ import static android.os.Process.ZYGOTE_PROCESS;
import static android.os.Process.getTotalMemory;
import static android.os.Process.isThreadInProcess;
import static android.os.Process.killProcess;
import static android.os.Process.killProcessGroup;
import static android.os.Process.killProcessQuiet;
import static android.os.Process.myPid;
import static android.os.Process.myUid;
@@ -969,13 +970,6 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            return false;
        }
        boolean doRemoveIfNoThreadInternal(int pid, ProcessRecord app) {
            if (app == null || app.getThread() != null) {
                return false;
            }
            return doRemoveInternal(pid, app);
        }
    }
    private final PendingStartActivityUids mPendingStartActivityUids;
@@ -1007,7 +1001,7 @@ public class ActivityManagerService extends IActivityManager.Stub
     * method.
     */
    @GuardedBy("this")
    void removePidLocked(int pid, ProcessRecord app) {
    boolean removePidLocked(int pid, ProcessRecord app) {
        final boolean removed;
        synchronized (mPidsSelfLocked) {
            removed = mPidsSelfLocked.doRemoveInternal(pid, app);
@@ -1018,26 +1012,6 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            mAtmInternal.onProcessUnMapped(pid);
        }
    }
    /**
     * Removes the process record from the map if it doesn't have a thread.
     * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
     * method.
     */
    @GuardedBy("this")
    private boolean removePidIfNoThreadLocked(ProcessRecord app) {
        final boolean removed;
        final int pid = app.getPid();
        synchronized (mPidsSelfLocked) {
            removed = mPidsSelfLocked.doRemoveIfNoThreadInternal(pid, app);
        }
        if (removed) {
            synchronized (sActiveProcessInfoSelfLocked) {
                sActiveProcessInfoSelfLocked.remove(pid);
            }
            mAtmInternal.onProcessUnMapped(pid);
        }
        return removed;
    }
@@ -2339,7 +2313,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mAppErrors = null;
        mPackageWatchdog = null;
        mAppOpsService = mInjector.getAppOpsService(null /* file */, null /* handler */);
        mBatteryStatsService = null;
        mBatteryStatsService = mInjector.getBatteryStatsService();
        mHandler = new MainHandler(handlerThread.getLooper());
        mHandlerThread = handlerThread;
        mConstants = new ActivityManagerConstants(mContext, this, mHandler);
@@ -2354,7 +2328,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mIntentFirewall = null;
        mProcessStats = new ProcessStatsService(this, mContext.getCacheDir());
        mCpHelper = new ContentProviderHelper(this, false);
        mServices = null;
        mServices = mInjector.getActiveServices(this);
        mSystemThread = null;
        mUiHandler = injector.getUiHandler(null /* service */);
        mUidObserverController = new UidObserverController(mUiHandler);
@@ -3301,8 +3275,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        ProcessRecord record = mProcessList.getLRURecordForAppLOSP(threadBinder);
        if (record != null) return record;
        // Validation: if it isn't in the LRU list, it shouldn't exist, but let's
        // double-check that.
        // Validation: if it isn't in the LRU list, it shouldn't exist, but let's double-check that.
        final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
                mProcessList.getProcessNamesLOSP().getMap();
        for (int i = pmap.size()-1; i >= 0; i--) {
@@ -3311,8 +3284,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                final ProcessRecord proc = procs.valueAt(j);
                final IApplicationThread procThread = proc.getThread();
                if (procThread != null && procThread.asBinder() == threadBinder) {
                    if (!proc.isPendingFinishAttach()) {
                        Slog.wtf(TAG, "getRecordForApp: exists in name list but not in LRU list: "
                                + proc);
                    }
                    return proc;
                }
            }
@@ -4744,7 +4719,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    @GuardedBy("this")
    void handleProcessStartOrKillTimeoutLocked(ProcessRecord app, boolean isKillTimeout) {
        final int pid = app.getPid();
        boolean gone = isKillTimeout || removePidIfNoThreadLocked(app);
        boolean gone = isKillTimeout || removePidLocked(pid, app);
        if (gone) {
            if (isKillTimeout) {
@@ -4825,7 +4800,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    }
    @GuardedBy("this")
    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
    private void attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
        // Find the application record that is being attached...  either via
@@ -4890,7 +4865,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    // Ignore exceptions.
                }
            }
            return false;
            return;
        }
        // If this application record is still attached to a previous
@@ -4915,7 +4890,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            mProcessList.startProcessLocked(app,
                    new HostingRecord(HostingRecord.HOSTING_TYPE_LINK_FAIL, processName),
                    ZYGOTE_POLICY_FLAG_EMPTY);
            return false;
            return;
        }
        EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
@@ -4938,8 +4913,6 @@ public class ActivityManagerService extends IActivityManager.Stub
            app.setUnlocked(StorageManager.isUserKeyUnlocked(app.userId));
        }
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List<ProviderInfo> providers = normalMode
                                            ? mCpHelper.generateApplicationProvidersLocked(app)
@@ -5090,6 +5063,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                profilerInfo = null;
            }
            app.setBindApplicationTime(bindApplicationTimeMillis);
            // Make app active after binding application or client may be running requests (e.g
            // starting activities) before it is ready.
            synchronized (mProcLock) {
@@ -5103,6 +5078,19 @@ public class ActivityManagerService extends IActivityManager.Stub
                app.mProfile.setLastRequestedGc(now);
                app.mProfile.setLastLowMemory(now);
            }
            // Remove this record from the list of starting applications.
            mPersistentStartingProcesses.remove(app);
            if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) {
                Slog.v(TAG_PROCESSES, "Attach application locked removing on hold: " + app);
            }
            mProcessesOnHold.remove(app);
            if (!mConstants.mEnableWaitForFinishAttachApplication) {
                finishAttachApplicationInner(startSeq, callingUid, pid);
            } else {
                app.setPendingFinishAttach(true);
            }
        } catch (Exception e) {
            // We need kill the process group here. (b/148588589)
            Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
@@ -5111,15 +5099,58 @@ public class ActivityManagerService extends IActivityManager.Stub
            app.killLocked("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
                    true);
            handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);
            return false;
            return;
        }
    }
        // Remove this record from the list of starting applications.
        mPersistentStartingProcesses.remove(app);
        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                "Attach application locked removing on hold: " + app);
        mProcessesOnHold.remove(app);
    @Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        if (thread == null) {
            throw new SecurityException("Invalid application interface");
        }
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }
    private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
        final long startTime = SystemClock.uptimeMillis();
        // Find the application record that is being attached...  either via
        // the pid if we are running in multiple processes, or just pull the
        // next app record if we are emulating process with anonymous threads.
        final ProcessRecord app;
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid);
        }
        if (app != null && app.getStartUid() == uid && app.getStartSeq() == startSeq) {
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        } else {
            Slog.wtf(TAG, "Mismatched or missing ProcessRecord: " + app + ". Pid: " + pid
                    + ". Uid: " + uid);
            killProcess(pid);
            killProcessGroup(uid, pid);
            mProcessList.noteAppKill(pid, uid,
                    ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
                    ApplicationExitInfo.SUBREASON_UNKNOWN,
                    "wrong startSeq");
            synchronized (this) {
                app.killLocked("unexpected process record",
                        ApplicationExitInfo.REASON_OTHER, true);
            }
            return;
        }
        synchronized (this) {
            // Mark the finish attach application phase as completed
            app.setPendingFinishAttach(false);
            final boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
            final String processName = app.processName;
            boolean badApp = false;
            boolean didSomething = false;
@@ -5137,7 +5168,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            if (!badApp) {
                try {
                    didSomething |= mServices.attachApplicationLocked(app, processName);
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
                    checkTime(startTime, "finishAttachApplicationInner: "
                            + "after mServices.attachApplicationLocked");
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                    badApp = true;
@@ -5150,7 +5182,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                    for (BroadcastQueue queue : mBroadcastQueues) {
                        didSomething |= queue.onApplicationAttachedLocked(app);
                    }
                checkTime(startTime, "attachApplicationLocked: after dispatching broadcasts");
                    checkTime(startTime, "finishAttachApplicationInner: "
                            + "after dispatching broadcasts");
                } catch (Exception e) {
                    // If the app died trying to launch the receiver we declare it 'bad'
                    Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
@@ -5159,13 +5192,17 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            // Check whether the next backup agent is in this process...
            final BackupRecord backupTarget = mBackupTargets.get(app.userId);
            if (!badApp && backupTarget != null && backupTarget.app == app) {
            if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
                if (DEBUG_BACKUP) {
                    Slog.v(TAG_BACKUP,
                            "New app is backup target, launching agent for " + app);
                }
                notifyPackageUse(backupTarget.appInfo.packageName,
                        PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
                try {
                thread.scheduleCreateBackupAgent(backupTarget.appInfo,
                    app.getThread().scheduleCreateBackupAgent(backupTarget.appInfo,
                            backupTarget.backupMode, backupTarget.userId,
                            backupTarget.backupDestination);
                } catch (Exception e) {
@@ -5175,20 +5212,19 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            if (badApp) {
            app.killLocked("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
                    true);
                app.killLocked("error during init",
                        ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
                handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);
            return false;
                return;
            }
            if (!didSomething) {
                updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
            checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
                checkTime(startTime, "finishAttachApplicationInner: after updateOomAdjLocked");
            }
            final HostingRecord hostingRecord = app.getHostingRecord();
        String shortAction = getShortAction(hostingRecord.getAction());
            final String shortAction = getShortAction(hostingRecord.getAction());
            FrameworkStatsLog.write(
                    FrameworkStatsLog.PROCESS_START_TIME,
                    app.info.uid,
@@ -5196,26 +5232,35 @@ public class ActivityManagerService extends IActivityManager.Stub
                    app.info.packageName,
                    FrameworkStatsLog.PROCESS_START_TIME__TYPE__COLD,
                    app.getStartElapsedTime(),
                (int) (bindApplicationTimeMillis - app.getStartUptime()),
                    (int) (app.getBindApplicationTime() - app.getStartUptime()),
                    (int) (SystemClock.uptimeMillis() - app.getStartUptime()),
                    hostingRecord.getType(),
                    hostingRecord.getName(),
                    shortAction,
                    HostingRecord.getHostingTypeIdStatsd(hostingRecord.getType()),
                    HostingRecord.getTriggerTypeForStatsd(hostingRecord.getTriggerType()));
        return true;
        }
    }
    @Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        if (thread == null) {
            throw new SecurityException("Invalid application interface");
    public final void finishAttachApplication(long startSeq) {
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();
        if (!mConstants.mEnableWaitForFinishAttachApplication) {
            Slog.i(TAG, "Flag disabled. Ignoring finishAttachApplication from uid: "
                    + uid + ". pid: " + pid);
            return;
        }
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
        if (pid == MY_PID && uid == SYSTEM_UID) {
            return;
        }
        final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        try {
            finishAttachApplicationInner(startSeq, uid, pid);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
@@ -19047,6 +19092,21 @@ public class ActivityManagerService extends IActivityManager.Stub
            return new ProcessList();
        }
        /**
         * Returns the {@link BatteryStatsService} instance
         */
        public BatteryStatsService getBatteryStatsService() {
            return new BatteryStatsService(mContext, SystemServiceManager.ensureSystemDir(),
                BackgroundThread.get().getHandler());
        }
        /**
         * Returns the {@link ActiveServices} instance
         */
        public ActiveServices getActiveServices(ActivityManagerService service) {
            return new ActiveServices(service);
        }
        private boolean ensureHasNetworkManagementInternal() {
            if (mNmi == null) {
                mNmi = LocalServices.getService(NetworkManagementInternal.class);
+1 −1
Original line number Diff line number Diff line
@@ -1243,7 +1243,7 @@ public class OomAdjuster {
        for (int i = numLru - 1; i >= 0; i--) {
            ProcessRecord app = lruList.get(i);
            final ProcessStateRecord state = app.mState;
            if (!app.isKilledByAm() && app.getThread() != null) {
            if (!app.isKilledByAm() && app.getThread() != null && !app.isPendingFinishAttach()) {
                // We don't need to apply the update for the process which didn't get computed
                if (state.getCompletedAdjSeq() == mAdjSeq) {
                    applyOomAdjLSP(app, true, now, nowElapsed, oomAdjReason);
Loading