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

Commit e54eb36e authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Report firstLaunch metrics

Track the stopped state and first launch state in the relevant
records, such as in BroadcastQueue and WindowProcessController
and reset at proper time. This fixes issues with the metrics for
stopped state.

Bug: 296644915
Test: atest ForceStopTest
      m statsd_testdrive; statsd_testdrive 48 475 476 477

Change-Id: Ic4508d770352ba61900f39d549b1fd82a2994c72
parent 0d5f65a7
Loading
Loading
Loading
Loading
+29 −4
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE_EXECUTING;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
@@ -1497,6 +1498,11 @@ public final class ActiveServices {
        FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, uid, packageName,
                serviceName, FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START);
        mAm.mBatteryStatsService.noteServiceStartRunning(uid, packageName, serviceName);
        final ProcessRecord hostApp = r.app;
        final boolean wasStopped = hostApp == null ? wasStopped(r) : false;
        final boolean firstLaunch =
                hostApp == null ? !mAm.wasPackageEverLaunched(r.packageName, r.userId) : false;

        String error = bringUpServiceLocked(r, service.getFlags(), callerFg,
                false /* whileRestarting */,
                false /* permissionsReviewRequired */,
@@ -1509,10 +1515,14 @@ public final class ActiveServices {
            return new ComponentName("!!", error);
        }

        final boolean wasStopped = (r.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0;
        final int packageState = wasStopped
                ? SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED
                : SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL;
        if (DEBUG_PROCESSES) {
            Slog.d(TAG, "Logging startService for " + packageName + ", stopped="
                    + wasStopped + ", firstLaunch=" + firstLaunch + ", intent=" + service
                    + ", r.app=" + r.app);
        }
        FrameworkStatsLog.write(SERVICE_REQUEST_EVENT_REPORTED, uid, callingUid,
                service.getAction(),
                SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__START, false,
@@ -1527,7 +1537,9 @@ public final class ActiveServices {
                packageName,
                callingPackage,
                callingProcessState,
                r.mProcessStateOnRequest);
                r.mProcessStateOnRequest,
                firstLaunch,
                0L /* TODO: stoppedDuration */);

        if (r.startRequested && addToStarting) {
            boolean first = smap.mStartingBackground.size() == 0;
@@ -4038,7 +4050,6 @@ public final class ActiveServices {
                mAm.requireAllowedAssociationsLocked(s.appInfo.packageName);
            }

            final boolean wasStopped = (s.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0;
            final boolean wasStartRequested = s.startRequested;
            final boolean hadConnections = !s.getConnections().isEmpty();
            mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
@@ -4113,6 +4124,10 @@ public final class ActiveServices {
                        true);
            }

            final boolean wasStopped = hostApp == null ? wasStopped(s) : false;
            final boolean firstLaunch =
                    hostApp == null ? !mAm.wasPackageEverLaunched(s.packageName, s.userId) : false;

            boolean needOomAdj = false;
            if (c.hasFlag(Context.BIND_AUTO_CREATE)) {
                s.lastActivity = SystemClock.uptimeMillis();
@@ -4155,6 +4170,10 @@ public final class ActiveServices {
            final int packageState = wasStopped
                    ? SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED
                    : SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL;
            if (DEBUG_PROCESSES) {
                Slog.d(TAG, "Logging bindService for " + s.packageName
                        + ", stopped=" + wasStopped + ", firstLaunch=" + firstLaunch);
            }
            FrameworkStatsLog.write(SERVICE_REQUEST_EVENT_REPORTED, s.appInfo.uid, callingUid,
                    ActivityManagerService.getShortAction(service.getAction()),
                    SERVICE_REQUEST_EVENT_REPORTED__REQUEST_TYPE__BIND, false,
@@ -4169,7 +4188,9 @@ public final class ActiveServices {
                    s.packageName,
                    callerApp.info.packageName,
                    callerApp.mState.getCurProcState(),
                    s.mProcessStateOnRequest);
                    s.mProcessStateOnRequest,
                    firstLaunch,
                    0L /* TODO */);

            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
                    + ": received=" + b.intent.received
@@ -9112,4 +9133,8 @@ public final class ActiveServices {
        return mCachedDeviceProvisioningPackage != null
                && mCachedDeviceProvisioningPackage.equals(packageName);
    }

    private boolean wasStopped(ServiceRecord serviceRecord) {
        return (serviceRecord.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0;
    }
}
+17 −2
Original line number Diff line number Diff line
@@ -5046,8 +5046,11 @@ public class ActivityManagerService extends IActivityManager.Stub
     * Send LOCKED_BOOT_COMPLETED and BOOT_COMPLETED to the package explicitly when unstopped
     */
    private void maybeSendBootCompletedLocked(ProcessRecord app) {
        if (!android.content.pm.Flags.stayStopped()) return;
        // Nothing to do if it wasn't previously stopped
        if (!android.content.pm.Flags.stayStopped() || !app.wasForceStopped()) return;
        if (!app.wasForceStopped() && !app.getWindowProcessController().wasForceStopped()) {
            return;
        }
        // Send LOCKED_BOOT_COMPLETED, if necessary
        if (app.getApplicationInfo().isEncryptionAware()) {
@@ -5059,7 +5062,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            sendBootBroadcastToAppLocked(app, new Intent(Intent.ACTION_BOOT_COMPLETED),
                    REASON_BOOT_COMPLETED);
        }
        app.setWasForceStopped(false);
        // The stopped state is reset in ProcessRecord when the pid changes, to deal with
        // any re-use of the ProcessRecord.
    }
    /** Send a boot_completed broadcast to app */
@@ -6844,6 +6848,17 @@ public class ActivityManagerService extends IActivityManager.Stub
        return mPermissionManagerInt;
    }
    /** Returns whether the given package was ever launched since install */
    boolean wasPackageEverLaunched(String packageName, @UserIdInt int userId) {
        boolean wasLaunched = false;
        try {
            wasLaunched = getPackageManagerInternal().wasPackageEverLaunched(packageName, userId);
        } catch (Exception e) {
            // If the package state record doesn't exist yet, assume it was never launched
        }
        return wasLaunched;
    }
    private TestUtilityService getTestUtilityServiceLocked() {
        if (mTestUtilityService == null) {
            mTestUtilityService =
+5 −2
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import com.android.internal.app.ProcessMap;
import com.android.server.IoThread;
import com.android.server.ServiceThread;
import com.android.server.SystemServiceManager;
import com.android.server.wm.WindowProcessController;

import java.io.File;
import java.io.FileInputStream;
@@ -385,8 +386,10 @@ public final class AppStartInfoTracker {
        start.setPackageName(app.info.packageName);
        if (android.content.pm.Flags.stayStopped()) {
            // TODO: Verify this is created at the right time to have the correct force-stopped
            // state in the ProcessRecord. Also use the WindowProcessRecord if activity.
            start.setForceStopped(app.wasForceStopped());
            // state in the ProcessRecord.
            final WindowProcessController wpc = app.getWindowProcessController();
            start.setForceStopped(app.wasForceStopped()
                    || (wpc != null ? wpc.wasForceStopped() : false));
        }
    }

+14 −0
Original line number Diff line number Diff line
@@ -180,6 +180,12 @@ class BroadcastProcessQueue {
     */
    private boolean mActiveWasStopped;

    /**
     * Flag indicating that the currently active broadcast is being dispatched
     * to a package that was never launched before.
     */
    private boolean mActiveFirstLaunch;

    /**
     * Number of consecutive urgent broadcasts that have been dispatched
     * since the last non-urgent dispatch.
@@ -596,6 +602,10 @@ class BroadcastProcessQueue {
        mActiveWasStopped = activeWasStopped;
    }

    public void setActiveFirstLaunch(boolean activeFirstLaunch) {
        mActiveFirstLaunch = activeFirstLaunch;
    }

    public boolean getActiveViaColdStart() {
        return mActiveViaColdStart;
    }
@@ -604,6 +614,10 @@ class BroadcastProcessQueue {
        return mActiveWasStopped;
    }

    public boolean getActiveFirstLaunch() {
        return mActiveFirstLaunch;
    }

    /**
     * Get package name of the first application loaded into this process.
     */
+15 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVE
import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL;
import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.LOG_WRITER_INFO;
import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList;
import static com.android.server.am.BroadcastProcessQueue.reasonToString;
@@ -966,6 +967,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            queue.setActiveWasStopped(true);
        }
        final int intentFlags = r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND;
        final boolean firstLaunch = !mService.wasPackageEverLaunched(info.packageName, r.userId);
        queue.setActiveFirstLaunch(firstLaunch);

        final HostingRecord hostingRecord = new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST,
                component, r.intent.getAction(), r.getHostingRecordTriggerType());
        final boolean isActivityCapable = (r.options != null
@@ -2108,6 +2112,12 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        final long dispatchDelay = r.scheduledTime[index] - r.enqueueTime;
        final long receiveDelay = 0;
        final long finishDelay = r.terminalTime[index] - r.scheduledTime[index];
        if (DEBUG_PROCESSES) {
            Slog.d(TAG, "Logging broadcast for "
                    + (app != null ? app.info.packageName : "<null>")
                    + ", stopped=" + queue.getActiveWasStopped()
                    + ", firstLaunch=" + queue.getActiveFirstLaunch());
        }
        if (queue != null) {
            final int packageState = queue.getActiveWasStopped()
                    ? SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED
@@ -2117,7 +2127,11 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
                    app != null ? app.info.packageName : null, r.callerPackage,
                    r.calculateTypeForLogging(), r.getDeliveryGroupPolicy(), r.intent.getFlags(),
                    BroadcastRecord.getReceiverPriority(receiver), r.callerProcState,
                    receiverProcessState);
                    receiverProcessState, queue.getActiveFirstLaunch(),
                    0L /* TODO: stoppedDuration */);
            // Reset the states after logging
            queue.setActiveFirstLaunch(false);
            queue.setActiveWasStopped(false);
        }
    }

Loading