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

Commit 8b20cdb2 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Add API to track usage time of apps." into mnc-dev

parents 95821eea b5a380d4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -3745,6 +3745,7 @@ package android.app {
  }
  public class ActivityOptions {
    method public static android.app.ActivityOptions makeBasic();
    method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
    method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
    method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
@@ -3752,8 +3753,11 @@ package android.app {
    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View, java.lang.String>...);
    method public static android.app.ActivityOptions makeTaskLaunchBehind();
    method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
    method public void requestUsageTimeReport(android.app.PendingIntent);
    method public android.os.Bundle toBundle();
    method public void update(android.app.ActivityOptions);
    field public static final java.lang.String EXTRA_USAGE_REPORT_PACKAGES = "android.package";
    field public static final java.lang.String EXTRA_USAGE_REPORT_TIME = "android.time";
  }
  public class AlarmManager {
+4 −0
Original line number Diff line number Diff line
@@ -3837,6 +3837,7 @@ package android.app {
  }
  public class ActivityOptions {
    method public static android.app.ActivityOptions makeBasic();
    method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
    method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
    method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
@@ -3844,8 +3845,11 @@ package android.app {
    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View, java.lang.String>...);
    method public static android.app.ActivityOptions makeTaskLaunchBehind();
    method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
    method public void requestUsageTimeReport(android.app.PendingIntent);
    method public android.os.Bundle toBundle();
    method public void update(android.app.ActivityOptions);
    field public static final java.lang.String EXTRA_USAGE_REPORT_PACKAGES = "android.package";
    field public static final java.lang.String EXTRA_USAGE_REPORT_TIME = "android.time";
  }
  public class AlarmManager {
+68 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.util.Pair;
import android.util.Slog;
import android.view.View;
import android.view.Window;

@@ -38,6 +39,19 @@ import java.util.ArrayList;
public class ActivityOptions {
    private static final String TAG = "ActivityOptions";

    /**
     * A long in the extras delivered by {@link #requestUsageTimeReport} that contains
     * the total time (in ms) the user spent in the app.
     */
    public static final String EXTRA_USAGE_REPORT_TIME = "android.time";

    /**
     * A Bundle in the extras delivered by {@link #requestUsageTimeReport} that contains
     * detailed information about the time spent in each package associated with the app;
     * each key is a package name, whose value is a long containing the time (in ms).
     */
    public static final String EXTRA_USAGE_REPORT_PACKAGES = "android.package";

    /**
     * The package name that created the options.
     * @hide
@@ -118,6 +132,8 @@ public class ActivityOptions {
    private static final String KEY_RESULT_CODE = "android:resultCode";
    private static final String KEY_EXIT_COORDINATOR_INDEX = "android:exitCoordinatorIndex";

    private static final String KEY_USAGE_TIME_REPORT = "android:usageTimeReport";

    /** @hide */
    public static final int ANIM_NONE = 0;
    /** @hide */
@@ -160,6 +176,7 @@ public class ActivityOptions {
    private Intent mResultData;
    private int mResultCode;
    private int mExitCoordinatorIndex;
    private PendingIntent mUsageTimeReport;

    /**
     * Create an ActivityOptions specifying a custom animation to run when
@@ -586,6 +603,15 @@ public class ActivityOptions {
        return opts;
    }

    /**
     * Create a basic ActivityOptions that has no special animation associated with it.
     * Other options can still be set.
     */
    public static ActivityOptions makeBasic() {
        final ActivityOptions opts = new ActivityOptions();
        return opts;
    }

    /** @hide */
    public boolean getLaunchTaskBehind() {
        return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -597,6 +623,11 @@ public class ActivityOptions {
    /** @hide */
    public ActivityOptions(Bundle opts) {
        mPackageName = opts.getString(KEY_PACKAGE_NAME);
        try {
            mUsageTimeReport = opts.getParcelable(KEY_USAGE_TIME_REPORT);
        } catch (RuntimeException e) {
            Slog.w(TAG, e);
        }
        mAnimationType = opts.getInt(KEY_ANIM_TYPE);
        switch (mAnimationType) {
            case ANIM_CUSTOM:
@@ -729,6 +760,11 @@ public class ActivityOptions {
    /** @hide */
    public Intent getResultData() { return mResultData; }

    /** @hide */
    public PendingIntent getUsageTimeReport() {
        return mUsageTimeReport;
    }

    /** @hide */
    public static void abort(Bundle options) {
        if (options != null) {
@@ -745,6 +781,7 @@ public class ActivityOptions {
        if (otherOptions.mPackageName != null) {
            mPackageName = otherOptions.mPackageName;
        }
        mUsageTimeReport = otherOptions.mUsageTimeReport;
        mTransitionReceiver = null;
        mSharedElementNames = null;
        mIsReturning = false;
@@ -828,6 +865,9 @@ public class ActivityOptions {
            b.putString(KEY_PACKAGE_NAME, mPackageName);
        }
        b.putInt(KEY_ANIM_TYPE, mAnimationType);
        if (mUsageTimeReport != null) {
            b.putParcelable(KEY_USAGE_TIME_REPORT, mUsageTimeReport);
        }
        switch (mAnimationType) {
            case ANIM_CUSTOM:
                b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
@@ -872,6 +912,34 @@ public class ActivityOptions {
        return b;
    }

    /**
     * Ask the the system track that time the user spends in the app being launched, and
     * report it back once done.  The report will be sent to the given receiver, with
     * the extras {@link #EXTRA_USAGE_REPORT_TIME} and {@link #EXTRA_USAGE_REPORT_PACKAGES}
     * filled in.
     *
     * <p>The time interval tracked is from launching this activity until the user leaves
     * that activity's flow.  They are considered to stay in the flow as long as
     * new activities are being launched or returned to from the original flow,
     * even if this crosses package or task boundaries.  For example, if the originator
     * starts an activity to view an image, and while there the user selects to share,
     * which launches their email app in a new task, and they complete the share, the
     * time during that entire operation will be included until they finally hit back from
     * the original image viewer activity.</p>
     *
     * <p>The user is considered to complete a flow once they switch to another
     * activity that is not part of the tracked flow.  This may happen, for example, by
     * using the notification shade, launcher, or recents to launch or switch to another
     * app.  Simply going in to these navigation elements does not break the flow (although
     * the launcher and recents stops time tracking of the session); it is the act of
     * going somewhere else that completes the tracking.</p>
     *
     * @param receiver A broadcast receiver that willl receive the report.
     */
    public void requestUsageTimeReport(PendingIntent receiver) {
        mUsageTimeReport = receiver;
    }

    /**
     * Return the filtered options only meant to be seen by the target activity itself
     * @hide
+47 −3
Original line number Diff line number Diff line
@@ -425,6 +425,11 @@ public final class ActivityManagerService extends ActivityManagerNative
     */
    private int mLastFocusedUserId;
    /**
     * If non-null, we are tracking the time the user spends in the currently focused app.
     */
    private AppTimeTracker mCurAppTimeTracker;
    /**
     * List of intents that were used to start the most recent tasks.
     */
@@ -1330,7 +1335,8 @@ public final class ActivityManagerService extends ActivityManagerNative
    static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 51;
    static final int DELETE_DUMPHEAP_MSG = 52;
    static final int FOREGROUND_PROFILE_CHANGED_MSG = 53;
    static final int DISPATCH_UIDS_CHANGED = 54;
    static final int DISPATCH_UIDS_CHANGED_MSG = 54;
    static final int REPORT_TIME_TRACKER_MSG = 55;
    static final int FIRST_ACTIVITY_STACK_MSG = 100;
    static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1563,7 +1569,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                dispatchProcessDied(pid, uid);
                break;
            }
            case DISPATCH_UIDS_CHANGED: {
            case DISPATCH_UIDS_CHANGED_MSG: {
                dispatchUidsChanged();
            } break;
            }
@@ -1988,6 +1994,10 @@ public final class ActivityManagerService extends ActivityManagerNative
            case FOREGROUND_PROFILE_CHANGED_MSG: {
                dispatchForegroundProfileChanged(msg.arg1);
            } break;
            case REPORT_TIME_TRACKER_MSG: {
                AppTimeTracker tracker = (AppTimeTracker)msg.obj;
                tracker.deliverResult(mContext);
            } break;
            }
        }
    };
@@ -2573,6 +2583,27 @@ public final class ActivityManagerService extends ActivityManagerNative
            if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);
            ActivityRecord last = mFocusedActivity;
            mFocusedActivity = r;
            if (r.task.taskType != ActivityRecord.HOME_ACTIVITY_TYPE
                    && r.task.taskType != ActivityRecord.RECENTS_ACTIVITY_TYPE) {
                if (mCurAppTimeTracker != r.appTimeTracker) {
                    // We are switching app tracking.  Complete the current one.
                    if (mCurAppTimeTracker != null) {
                        mCurAppTimeTracker.stop();
                        mHandler.obtainMessage(REPORT_TIME_TRACKER_MSG,
                                mCurAppTimeTracker).sendToTarget();
                        mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);
                        mCurAppTimeTracker = null;
                    }
                    if (r.appTimeTracker != null) {
                        mCurAppTimeTracker = r.appTimeTracker;
                        startTimeTrackingFocusedActivityLocked();
                    }
                } else {
                    startTimeTrackingFocusedActivityLocked();
                }
            } else {
                r.appTimeTracker = null;
            }
            if (r.task != null && r.task.voiceInteractor != null) {
                startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
            } else {
@@ -10132,14 +10163,24 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    void startTimeTrackingFocusedActivityLocked() {
        if (!mSleeping && mCurAppTimeTracker != null && mFocusedActivity != null) {
            mCurAppTimeTracker.start(mFocusedActivity.packageName);
        }
    }
    void updateSleepIfNeededLocked() {
        if (mSleeping && !shouldSleepLocked()) {
            mSleeping = false;
            startTimeTrackingFocusedActivityLocked();
            mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
            mStackSupervisor.comeOutOfSleepIfNeededLocked();
            updateOomAdjLocked();
        } else if (!mSleeping && shouldSleepLocked()) {
            mSleeping = true;
            if (mCurAppTimeTracker != null) {
                mCurAppTimeTracker.stop();
            }
            mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
            mStackSupervisor.goingToSleepLocked();
            updateOomAdjLocked();
@@ -13342,6 +13383,9 @@ public final class ActivityManagerService extends ActivityManagerNative
                        + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
            }
        }
        if (mCurAppTimeTracker != null) {
            mCurAppTimeTracker.dumpWithHeader(pw, "  ", true);
        }
        if (mMemWatchProcesses.getMap().size() > 0) {
            pw.println("  Mem watch processes:");
            final ArrayMap<String, SparseArray<Pair<Long, String>>> procs
@@ -18460,7 +18504,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            if (mPendingUidChanges.size() == 0) {
                if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                        "*** Enqueueing dispatch uid changed!");
                mUiHandler.obtainMessage(DISPATCH_UIDS_CHANGED).sendToTarget();
                mUiHandler.obtainMessage(DISPATCH_UIDS_CHANGED_MSG).sendToTarget();
            }
            final int NA = mAvailUidChanges.size();
            if (NA > 0) {
+9 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.*;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;

import android.app.ActivityManager.TaskDescription;
import android.app.PendingIntent;
import android.os.PersistableBundle;
import android.os.Trace;

@@ -142,6 +143,7 @@ final class ActivityRecord {
    ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
    ActivityOptions pendingOptions; // most recently given options
    ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
    AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
    HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
    UriPermissionOwner uriPermissions; // current special URI access perms.
    ProcessRecord app;      // if non-null, hosting application
@@ -262,6 +264,9 @@ final class ActivityRecord {
        if (pendingOptions != null) {
            pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
        }
        if (appTimeTracker != null) {
            appTimeTracker.dumpWithHeader(pw, prefix, false);
        }
        if (uriPermissions != null) {
            uriPermissions.dump(pw, prefix);
        }
@@ -463,6 +468,10 @@ final class ActivityRecord {
        if (options != null) {
            pendingOptions = new ActivityOptions(options);
            mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
            PendingIntent usageReport = pendingOptions.getUsageTimeReport();
            if (usageReport != null) {
                appTimeTracker = new AppTimeTracker(usageReport);
            }
        }

        // This starts out true, since the initial state of an activity
Loading