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

Commit c60f010e authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am 8b20cdb2: Merge "Add API to track usage time of apps." into mnc-dev

* commit '8b20cdb2':
  Add API to track usage time of apps.
parents 53d3e8c9 8b20cdb2
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