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

Commit 81f97775 authored by Hui Yu's avatar Hui Yu Committed by Android (Google) Code Review
Browse files

Merge "Add UsageStats events for foreground service start/stop."

parents 3bd12f7d e361a23b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -7580,6 +7580,8 @@ package android.app.usage {
    method public java.lang.String getShortcutId();
    method public long getTimeStamp();
    field public static final int CONFIGURATION_CHANGE = 5; // 0x5
    field public static final int FOREGROUND_SERVICE_START = 19; // 0x13
    field public static final int FOREGROUND_SERVICE_STOP = 20; // 0x14
    field public static final int KEYGUARD_HIDDEN = 18; // 0x12
    field public static final int KEYGUARD_SHOWN = 17; // 0x11
    field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
@@ -7597,9 +7599,11 @@ package android.app.usage {
    method public void add(android.app.usage.UsageStats);
    method public int describeContents();
    method public long getFirstTimeStamp();
    method public long getLastTimeForegroundServiceUsed();
    method public long getLastTimeStamp();
    method public long getLastTimeUsed();
    method public java.lang.String getPackageName();
    method public long getTotalTimeForegroundServiceUsed();
    method public long getTotalTimeInForeground();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.app.usage.UsageStats> CREATOR;
+44 −3
Original line number Diff line number Diff line
@@ -50,12 +50,20 @@ public final class UsageEvents implements Parcelable {
        public static final int NONE = 0;

        /**
         * An event type denoting that a component moved to the foreground.
         * An event type denoting that an {@link android.app.Activity} moved to the foreground.
         * This event has a package name and class name associated with it and can be retrieved
         * using {@link #getPackageName()} and {@link #getClassName()}.
         * If a package has multiple activities, this event is reported for each activity that moves
         * to foreground.
         */
        public static final int MOVE_TO_FOREGROUND = 1;

        /**
         * An event type denoting that a component moved to the background.
         * An event type denoting that an {@link android.app.Activity} moved to the background.
         * This event has a package name and class name associated with it and can be retrieved
         * using {@link #getPackageName()} and {@link #getClassName()}.
         * If a package has multiple activities, this event is reported for each activity that moves
         * to background.
         */
        public static final int MOVE_TO_BACKGROUND = 2;

@@ -165,11 +173,44 @@ public final class UsageEvents implements Parcelable {
         */
        public static final int KEYGUARD_HIDDEN = 18;

        /**
         * An event type denoting start of a foreground service.
         * This event has a package name and class name associated with it and can be retrieved
         * using {@link #getPackageName()} and {@link #getClassName()}.
         * If a package has multiple foreground services, this event is reported for each service
         * that is started.
         */
        public static final int FOREGROUND_SERVICE_START = 19;

        /**
         * An event type denoting stop of a foreground service.
         * This event has a package name and class name associated with it and can be retrieved
         * using {@link #getPackageName()} and {@link #getClassName()}.
         * If a package has multiple foreground services, this event is reported for each service
         * that is stopped.
         */
        public static final int FOREGROUND_SERVICE_STOP = 20;

        /**
         * An event type denoting that a foreground service is at started state at beginning of a
         * time interval.
         * This is effectively treated as a {@link #FOREGROUND_SERVICE_START}.
         * {@hide}
         */
        public static final int CONTINUING_FOREGROUND_SERVICE = 21;

        /**
         * An event type denoting that a foreground service is at started state when the stats
         * rolled-over at the end of a time interval.
         * {@hide}
         */
        public static final int ROLLOVER_FOREGROUND_SERVICE = 22;

        /**
         * Keep in sync with the greatest event type value.
         * @hide
         */
        public static final int MAX_EVENT_TYPE = 18;
        public static final int MAX_EVENT_TYPE = 22;

        /** @hide */
        public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
+271 −5
Original line number Diff line number Diff line
@@ -16,6 +16,15 @@

package android.app.usage;

import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
import static android.app.usage.UsageEvents.Event.END_OF_DAY;
import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;

import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Bundle;
@@ -48,18 +57,31 @@ public final class UsageStats implements Parcelable {
    public long mEndTimeStamp;

    /**
     * Last time used by the user with an explicit action (notification, activity launch).
     * Last time used by the user with an explicit action (notification, activity launch)
     * {@hide}
     */
    @UnsupportedAppUsage
    public long mLastTimeUsed;

    /**
     * Total time this package's activity is in foreground.
     * {@hide}
     */
    @UnsupportedAppUsage
    public long mTotalTimeInForeground;

    /**
     * Last time foreground service is started.
     * {@hide}
     */
    public long mLastTimeForegroundServiceUsed;

    /**
     * Total time this package's foreground service is started.
     * {@hide}
     */
    public long mTotalTimeForegroundServiceUsed;

    /**
     * {@hide}
     */
@@ -71,16 +93,36 @@ public final class UsageStats implements Parcelable {
     */
    public int mAppLaunchCount;

    /**
    /** Last activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
     * {@hide}
     * @deprecated use {@link #mLastForegroundActivityEventMap} instead.
     */
    @UnsupportedAppUsage
    @Deprecated
    public int mLastEvent;

    /**
     * If an activity is in foreground, it has one entry in this map.
     * When activity moves to background, it is removed from this map.
     * Key is activity class name.
     * Value is last time this activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
     * {@hide}
     */
    public ArrayMap<String, Integer> mLastForegroundActivityEventMap = new ArrayMap<>();

    /**
     * If a foreground service is started, it has one entry in this map.
     * When a foreground service is stopped, it is removed from this map.
     * Key is foreground service class name.
     * Value is last foreground service FOREGROUND_SERVICE_START ot FOREGROUND_SERVICE_STOP event.
     * {@hide}
     */
    public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts;
    public ArrayMap<String, Integer> mLastForegroundServiceEventMap = new ArrayMap<>();

    /**
     * {@hide}
     */
    public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts = new ArrayMap<>();

    /**
     * {@hide}
@@ -93,10 +135,14 @@ public final class UsageStats implements Parcelable {
        mBeginTimeStamp = stats.mBeginTimeStamp;
        mEndTimeStamp = stats.mEndTimeStamp;
        mLastTimeUsed = stats.mLastTimeUsed;
        mLastTimeForegroundServiceUsed = stats.mLastTimeForegroundServiceUsed;
        mTotalTimeInForeground = stats.mTotalTimeInForeground;
        mTotalTimeForegroundServiceUsed = stats.mTotalTimeForegroundServiceUsed;
        mLaunchCount = stats.mLaunchCount;
        mAppLaunchCount = stats.mAppLaunchCount;
        mLastEvent = stats.mLastEvent;
        mLastForegroundActivityEventMap = stats.mLastForegroundActivityEventMap;
        mLastForegroundServiceEventMap = stats.mLastForegroundServiceEventMap;
        mChooserCounts = stats.mChooserCounts;
    }

@@ -136,7 +182,7 @@ public final class UsageStats implements Parcelable {
    }

    /**
     * Get the last time this package was used, measured in milliseconds since the epoch.
     * Get the last time this package's activity was used, measured in milliseconds since the epoch.
     * <p/>
     * See {@link System#currentTimeMillis()}.
     */
@@ -151,6 +197,23 @@ public final class UsageStats implements Parcelable {
        return mTotalTimeInForeground;
    }

    /**
     * Get the last time this package's foreground service was used, measured in milliseconds since
     * the epoch.
     * <p/>
     * See {@link System#currentTimeMillis()}.
     */
    public long getLastTimeForegroundServiceUsed() {
        return mLastTimeForegroundServiceUsed;
    }

    /**
     * Get the total time this package's foreground services are started, measured in milliseconds.
     */
    public long getTotalTimeForegroundServiceUsed() {
        return mTotalTimeForegroundServiceUsed;
    }

    /**
     * Returns the number of times the app was launched as an activity from outside of the app.
     * Excludes intra-app activity transitions.
@@ -161,6 +224,19 @@ public final class UsageStats implements Parcelable {
        return mAppLaunchCount;
    }

    private void mergeEventMap(ArrayMap<String, Integer> left, ArrayMap<String, Integer> right) {
        final int size = right.size();
        for (int i = 0; i < size; i++) {
            final String className = right.keyAt(i);
            final Integer event = right.valueAt(i);
            if (left.containsKey(className)) {
                left.put(className, Math.max(left.get(className), event));
            } else {
                left.put(className, event);
            }
        }
    }

    /**
     * Add the statistics from the right {@link UsageStats} to the left. The package name for
     * both {@link UsageStats} objects must be the same.
@@ -179,12 +255,16 @@ public final class UsageStats implements Parcelable {
        if (right.mBeginTimeStamp > mBeginTimeStamp) {
            // Even though incoming UsageStat begins after this one, its last time used fields
            // may somehow be empty or chronologically preceding the older UsageStat.
            mLastEvent = Math.max(mLastEvent, right.mLastEvent);
            mergeEventMap(mLastForegroundActivityEventMap, right.mLastForegroundActivityEventMap);
            mergeEventMap(mLastForegroundServiceEventMap, right.mLastForegroundServiceEventMap);
            mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed);
            mLastTimeForegroundServiceUsed = Math.max(mLastTimeForegroundServiceUsed,
                    right.mLastTimeForegroundServiceUsed);
        }
        mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
        mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
        mTotalTimeInForeground += right.mTotalTimeInForeground;
        mTotalTimeForegroundServiceUsed += right.mTotalTimeForegroundServiceUsed;
        mLaunchCount += right.mLaunchCount;
        mAppLaunchCount += right.mAppLaunchCount;
        if (mChooserCounts == null) {
@@ -209,6 +289,161 @@ public final class UsageStats implements Parcelable {
        }
    }

    /**
     * Tell if an event indicate activity is in foreground or not.
     * @param event the activity event.
     * @return true if activity is in foreground, false otherwise.
     * @hide
     */
    private boolean isActivityInForeground(int event) {
        return event == MOVE_TO_FOREGROUND
                || event == CONTINUE_PREVIOUS_DAY;
    }

    /**
     * Tell if an event indicate foreground sevice is started or not.
     * @param event the foreground service event.
     * @return true if foreground service is started, false if stopped.
     * @hide
     */
    private boolean isForegroundServiceStarted(int event) {
        return event == FOREGROUND_SERVICE_START
                || event == CONTINUING_FOREGROUND_SERVICE;
    }

    /**
     * If any activity in foreground or any foreground service is started, the app is considered in
     * use.
     * @return true if in use, false otherwise.
     * @hide
     */
    private boolean isAppInUse() {
        return !mLastForegroundActivityEventMap.isEmpty()
                || !mLastForegroundServiceEventMap.isEmpty();
    }

    /**
     * Update by an event of an activity.
     * @param className className of the activity.
     * @param timeStamp timeStamp of the event.
     * @param eventType type of the event.
     * @hide
     */
    private void updateForegroundActivity(String className, long timeStamp, int eventType) {
        if (eventType != MOVE_TO_BACKGROUND
                && eventType != MOVE_TO_FOREGROUND
                && eventType != END_OF_DAY) {
            return;
        }

        final Integer lastEvent = mLastForegroundActivityEventMap.get(className);
        if (lastEvent != null) {
            if (isActivityInForeground(lastEvent)) {
                if (timeStamp > mLastTimeUsed) {
                    mTotalTimeInForeground += timeStamp - mLastTimeUsed;
                    mLastTimeUsed = timeStamp;
                }
            }
            if (eventType == MOVE_TO_BACKGROUND) {
                mLastForegroundActivityEventMap.remove(className);
            } else {
                mLastForegroundActivityEventMap.put(className, eventType);
            }
        } else if (eventType == MOVE_TO_FOREGROUND) {
            if (!isAppInUse()) {
                mLastTimeUsed = timeStamp;
            }
            mLastForegroundActivityEventMap.put(className, eventType);
        }
    }

    /**
     * Update by an event of an foreground service.
     * @param className className of the foreground service.
     * @param timeStamp timeStamp of the event.
     * @param eventType type of the event.
     * @hide
     */
    private void updateForegroundService(String className, long timeStamp, int eventType) {
        if (eventType != FOREGROUND_SERVICE_STOP
                && eventType != FOREGROUND_SERVICE_START
                && eventType != ROLLOVER_FOREGROUND_SERVICE) {
            return;
        }
        final Integer lastEvent = mLastForegroundServiceEventMap.get(className);
        if (lastEvent != null) {
            if (isForegroundServiceStarted(lastEvent)) {
                if (timeStamp > mLastTimeForegroundServiceUsed) {
                    mTotalTimeForegroundServiceUsed +=
                            timeStamp - mLastTimeForegroundServiceUsed;
                    mLastTimeForegroundServiceUsed = timeStamp;
                }
            }
            if (eventType == FOREGROUND_SERVICE_STOP) {
                mLastForegroundServiceEventMap.remove(className);
            } else {
                mLastForegroundServiceEventMap.put(className, eventType);
            }
        } else if (eventType == FOREGROUND_SERVICE_START) {
            if (!isAppInUse()) {
                mLastTimeForegroundServiceUsed = timeStamp;
            }
            mLastForegroundServiceEventMap.put(className, eventType);
        }
    }

    /**
     * Update the UsageStats by a activity or foreground service event.
     * @param className class name of a activity or foreground service, could be null to mark
     *                  END_OF_DAY or rollover.
     * @param timeStamp Epoch timestamp in milliseconds.
     * @param eventType event type as in {@link UsageEvents.Event}
     * @hide
     */
    public void update(String className, long timeStamp, int eventType) {
        switch(eventType) {
            case MOVE_TO_BACKGROUND:
            case MOVE_TO_FOREGROUND:
                updateForegroundActivity(className, timeStamp, eventType);
                break;
            case END_OF_DAY:
                // END_OF_DAY means updating all activities.
                final int size = mLastForegroundActivityEventMap.size();
                for (int i = 0; i < size; i++) {
                    final String name = mLastForegroundActivityEventMap.keyAt(i);
                    updateForegroundActivity(name, timeStamp, eventType);
                }
                break;
            case CONTINUE_PREVIOUS_DAY:
                mLastTimeUsed = timeStamp;
                mLastForegroundActivityEventMap.put(className, eventType);
                break;
            case FOREGROUND_SERVICE_STOP:
            case FOREGROUND_SERVICE_START:
                updateForegroundService(className, timeStamp, eventType);
                break;
            case ROLLOVER_FOREGROUND_SERVICE:
                // ROLLOVER_FOREGROUND_SERVICE means updating all foreground services.
                final int size2 = mLastForegroundServiceEventMap.size();
                for (int i = 0; i < size2; i++) {
                    final String name = mLastForegroundServiceEventMap.keyAt(i);
                    updateForegroundService(name, timeStamp, eventType);
                }
                break;
            case CONTINUING_FOREGROUND_SERVICE:
                mLastTimeForegroundServiceUsed = timeStamp;
                mLastForegroundServiceEventMap.put(className, eventType);
                break;
            default:
                break;
        }
        mEndTimeStamp = timeStamp;

        if (eventType == MOVE_TO_FOREGROUND) {
            mLaunchCount += 1;
        }
    }

    @Override
    public int describeContents() {
        return 0;
@@ -220,7 +455,9 @@ public final class UsageStats implements Parcelable {
        dest.writeLong(mBeginTimeStamp);
        dest.writeLong(mEndTimeStamp);
        dest.writeLong(mLastTimeUsed);
        dest.writeLong(mLastTimeForegroundServiceUsed);
        dest.writeLong(mTotalTimeInForeground);
        dest.writeLong(mTotalTimeForegroundServiceUsed);
        dest.writeInt(mLaunchCount);
        dest.writeInt(mAppLaunchCount);
        dest.writeInt(mLastEvent);
@@ -239,6 +476,22 @@ public final class UsageStats implements Parcelable {
            }
        }
        dest.writeBundle(allCounts);

        final Bundle foregroundActivityEventBundle = new Bundle();
        final int foregroundEventSize = mLastForegroundActivityEventMap.size();
        for (int i = 0; i < foregroundEventSize; i++) {
            foregroundActivityEventBundle.putInt(mLastForegroundActivityEventMap.keyAt(i),
                    mLastForegroundActivityEventMap.valueAt(i));
        }
        dest.writeBundle(foregroundActivityEventBundle);

        final Bundle foregroundServiceEventBundle = new Bundle();
        final int foregroundServiceEventSize = mLastForegroundServiceEventMap.size();
        for (int i = 0; i < foregroundServiceEventSize; i++) {
            foregroundServiceEventBundle.putInt(mLastForegroundServiceEventMap.keyAt(i),
                    mLastForegroundServiceEventMap.valueAt(i));
        }
        dest.writeBundle(foregroundServiceEventBundle);
    }

    public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -249,7 +502,9 @@ public final class UsageStats implements Parcelable {
            stats.mBeginTimeStamp = in.readLong();
            stats.mEndTimeStamp = in.readLong();
            stats.mLastTimeUsed = in.readLong();
            stats.mLastTimeForegroundServiceUsed = in.readLong();
            stats.mTotalTimeInForeground = in.readLong();
            stats.mTotalTimeForegroundServiceUsed = in.readLong();
            stats.mLaunchCount = in.readInt();
            stats.mAppLaunchCount = in.readInt();
            stats.mLastEvent = in.readInt();
@@ -272,9 +527,20 @@ public final class UsageStats implements Parcelable {
                    }
                }
            }
            readBundleToEventMap(stats.mLastForegroundActivityEventMap, in.readBundle());
            readBundleToEventMap(stats.mLastForegroundServiceEventMap, in.readBundle());
            return stats;
        }

        private void readBundleToEventMap(ArrayMap<String, Integer> eventMap, Bundle bundle) {
            if (bundle != null) {
                for (String className : bundle.keySet()) {
                    final int event = bundle.getInt(className);
                    eventMap.put(className, event);
                }
            }
        }

        @Override
        public UsageStats[] newArray(int size) {
            return new UsageStats[size];
+4 −1
Original line number Diff line number Diff line
@@ -192,7 +192,10 @@ public final class UsageStatsManager {
    public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C;
    /** @hide */
    public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;

    /** @hide */
    public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_START = 0x000E;
    /** @hide */
    public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP = 0x000F;
    /** @hide */
    public static final int REASON_SUB_PREDICTED_RESTORED       = 0x0001;

+6 −0
Original line number Diff line number Diff line
@@ -45,11 +45,15 @@ message IntervalStatsProto {
    optional string package = 1;
    // package_index contains the index + 1 of the package name in the string pool
    optional int32 package_index = 2;
    // Time attributes stored as an offset of the IntervalStats's beginTime.
    optional int64 last_time_active_ms = 3;
    optional int64 total_time_active_ms = 4;
    optional int32 last_event = 5;
    optional int32 app_launch_count = 6;
    repeated ChooserAction chooser_actions = 7;
    // Time attributes stored as an offset of the IntervalStats's beginTime.
    optional int64 last_time_service_used_ms = 8;
    optional int64 total_time_service_used_ms = 9;
  }

  // Stores the relevant information an IntervalStats will have about a Configuration
@@ -86,6 +90,8 @@ message IntervalStatsProto {
  // stringpool contains all the package and class names used by UsageStats and Event
  // They will hold a number that is equal to the index + 1 of their string in the pool
  optional StringPool stringpool = 2;
  optional int32 major_version = 3;
  optional int32 minor_version = 4;

  // The following fields contain aggregated usage stats data
  optional CountAndTime interactive = 10;
Loading