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

Commit 980b453e authored by Amith Yamasani's avatar Amith Yamasani Committed by android-build-merger
Browse files

Merge "Provide app launch count in UsageStats" into pi-dev

am: 8808edb0

Change-Id: I62a73e647fcbfffe5a56fe8229d8fb79738e2a80
parents 359b0116 8808edb0
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ package android {
    field public static final java.lang.String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
    field public static final java.lang.String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP";
    field public static final java.lang.String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS";
    field public static final java.lang.String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
    field public static final java.lang.String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
    field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
    field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
@@ -733,6 +734,10 @@ package android.app.usage {
    field public static final int SYSTEM_INTERACTION = 6; // 0x6
  }

  public final class UsageStats implements android.os.Parcelable {
    method public int getAppLaunchCount();
  }

  public final class UsageStatsManager {
    method public int getAppStandbyBucket(java.lang.String);
    method public java.util.Map<java.lang.String, java.lang.Integer> getAppStandbyBuckets();
+20 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.app.usage;

import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -58,6 +59,11 @@ public final class UsageStats implements Parcelable {
     */
    public int mLaunchCount;

    /**
     * {@hide}
     */
    public int mAppLaunchCount;

    /**
     * {@hide}
     */
@@ -81,6 +87,7 @@ public final class UsageStats implements Parcelable {
        mLastTimeUsed = stats.mLastTimeUsed;
        mTotalTimeInForeground = stats.mTotalTimeInForeground;
        mLaunchCount = stats.mLaunchCount;
        mAppLaunchCount = stats.mAppLaunchCount;
        mLastEvent = stats.mLastEvent;
        mChooserCounts = stats.mChooserCounts;
    }
@@ -136,6 +143,16 @@ public final class UsageStats implements Parcelable {
        return mTotalTimeInForeground;
    }

    /**
     * Returns the number of times the app was launched as an activity from outside of the app.
     * Excludes intra-app activity transitions.
     * @hide
     */
    @SystemApi
    public int getAppLaunchCount() {
        return mAppLaunchCount;
    }

    /**
     * Add the statistics from the right {@link UsageStats} to the left. The package name for
     * both {@link UsageStats} objects must be the same.
@@ -161,6 +178,7 @@ public final class UsageStats implements Parcelable {
        mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
        mTotalTimeInForeground += right.mTotalTimeInForeground;
        mLaunchCount += right.mLaunchCount;
        mAppLaunchCount += right.mAppLaunchCount;
        if (mChooserCounts == null) {
            mChooserCounts = right.mChooserCounts;
        } else if (right.mChooserCounts != null) {
@@ -196,6 +214,7 @@ public final class UsageStats implements Parcelable {
        dest.writeLong(mLastTimeUsed);
        dest.writeLong(mTotalTimeInForeground);
        dest.writeInt(mLaunchCount);
        dest.writeInt(mAppLaunchCount);
        dest.writeInt(mLastEvent);
        Bundle allCounts = new Bundle();
        if (mChooserCounts != null) {
@@ -224,6 +243,7 @@ public final class UsageStats implements Parcelable {
            stats.mLastTimeUsed = in.readLong();
            stats.mTotalTimeInForeground = in.readLong();
            stats.mLaunchCount = in.readInt();
            stats.mAppLaunchCount = in.readInt();
            stats.mLastEvent = in.readInt();
            Bundle allCounts = in.readBundle();
            if (allCounts != null) {
+18 −14
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app.usage;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -518,26 +519,28 @@ public final class UsageStatsManager {
    /**
     * @hide
     * Register an app usage limit observer that receives a callback on the provided intent when
     * the sum of usages of apps in the packages array exceeds the timeLimit specified. The
     * the sum of usages of apps in the packages array exceeds the {@code timeLimit} specified. The
     * observer will automatically be unregistered when the time limit is reached and the intent
     * is delivered.
     * is delivered. Registering an {@code observerId} that was already registered will override
     * the previous one.
     * @param observerId A unique id associated with the group of apps to be monitored. There can
     *                  be multiple groups with common packages and different time limits.
     * @param packages The list of packages to observe for foreground activity time. Must include
     *                 at least one package.
     * @param packages The list of packages to observe for foreground activity time. Cannot be null
     *                 and must include at least one package.
     * @param timeLimit The total time the set of apps can be in the foreground before the
     *                  callbackIntent is delivered. Must be greater than 0.
     * @param timeUnit The unit for time specified in timeLimit.
     * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
     * @param callbackIntent The PendingIntent that will be dispatched when the time limit is
     *                       exceeded by the group of apps. The delivered Intent will also contain
     *                       the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and
     *                       {@link #EXTRA_TIME_USED}.
     * @throws SecurityException if the caller doesn't have the PACKAGE_USAGE_STATS permission.
     *                       {@link #EXTRA_TIME_USED}. Cannot be null.
     * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission or
     *                           is not the profile owner of this user.
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
    public void registerAppUsageObserver(int observerId, String[] packages, long timeLimit,
            TimeUnit timeUnit, PendingIntent callbackIntent) {
    @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
    public void registerAppUsageObserver(int observerId, @NonNull String[] packages, long timeLimit,
            @NonNull TimeUnit timeUnit, @NonNull PendingIntent callbackIntent) {
        try {
            mService.registerAppUsageObserver(observerId, packages, timeUnit.toMillis(timeLimit),
                    callbackIntent, mContext.getOpPackageName());
@@ -547,14 +550,15 @@ public final class UsageStatsManager {

    /**
     * @hide
     * Unregister the app usage observer specified by the observerId. This will only apply to any
     * observer registered by this application. Unregistering an observer that was already
     * Unregister the app usage observer specified by the {@code observerId}. This will only apply
     * to any observer registered by this application. Unregistering an observer that was already
     * unregistered or never registered will have no effect.
     * @param observerId The id of the observer that was previously registered.
     * @throws SecurityException if the caller doesn't have the PACKAGE_USAGE_STATS permission.
     * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission or is
     *                           not the profile owner of this user.
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
    @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
    public void unregisterAppUsageObserver(int observerId) {
        try {
            mService.unregisterAppUsageObserver(observerId, mContext.getOpPackageName());
+5 −0
Original line number Diff line number Diff line
@@ -3290,6 +3290,11 @@
        android:protectionLevel="signature|privileged|development|appop" />
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />

    <!-- @hide @SystemApi Allows an application to observe usage time of apps. The app can register
         for callbacks when apps reach a certain usage time limit, etc. -->
    <permission android:name="android.permission.OBSERVE_APP_USAGE"
        android:protectionLevel="signature|privileged" />

    <!-- @hide @SystemApi Allows an application to change the app idle state of an app.
         <p>Not for use by third-party applications. -->
    <permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
+3 −18
Original line number Diff line number Diff line
@@ -71,16 +71,13 @@ public class AppTimeLimitController {
        /** The time when the current app came to the foreground */
        private long currentForegroundedTime;

        /** The last app that was in the background */
        private String lastBackgroundedPackage;

        /** Map from package name for quick lookup */
        private ArrayMap<String, ArrayList<TimeLimitGroup>> packageMap = new ArrayMap<>();

        /** Map of observerId to details of the time limit group */
        private SparseArray<TimeLimitGroup> groups = new SparseArray<>();

        UserData(@UserIdInt int userId) {
        private UserData(@UserIdInt int userId) {
            this.userId = userId;
        }
    }
@@ -114,7 +111,7 @@ public class AppTimeLimitController {
        int userId;
    }

    class MyHandler extends Handler {
    private class MyHandler extends Handler {

        static final int MSG_CHECK_TIMEOUT = 1;
        static final int MSG_INFORM_LISTENER = 2;
@@ -151,7 +148,7 @@ public class AppTimeLimitController {
    }

    /** Returns an existing UserData object for the given userId, or creates one */
    UserData getOrCreateUserDataLocked(int userId) {
    private UserData getOrCreateUserDataLocked(int userId) {
        UserData userData = mUsers.get(userId);
        if (userData == null) {
            userData = new UserData(userId);
@@ -258,12 +255,6 @@ public class AppTimeLimitController {
            user.currentForegroundedPackage = packageName;
            user.currentForegroundedTime = getUptimeMillis();

            // Check if the last package that was backgrounded is the same as this one
            if (!TextUtils.equals(packageName, user.lastBackgroundedPackage)) {
                // TODO: Move this logic up to usage stats to persist there.
                incTotalLaunchesLocked(user, packageName);
            }

            // Check if any of the groups need to watch for this package
            maybeWatchForPackageLocked(user, packageName, user.currentForegroundedTime);
        }
@@ -279,7 +270,6 @@ public class AppTimeLimitController {
    public void moveToBackground(String packageName, String className, int userId) {
        synchronized (mLock) {
            UserData user = getOrCreateUserDataLocked(userId);
            user.lastBackgroundedPackage = packageName;
            if (!TextUtils.equals(user.currentForegroundedPackage, packageName)) {
                Slog.w(TAG, "Eh? Last foregrounded package = " + user.currentForegroundedPackage
                        + " and now backgrounded = " + packageName);
@@ -433,10 +423,6 @@ public class AppTimeLimitController {
        }
    }

    private void incTotalLaunchesLocked(UserData user, String packageName) {
        // TODO: Inform UsageStatsService and aggregate the counter per app
    }

    void dump(PrintWriter pw) {
        synchronized (mLock) {
            pw.println("\n  App Time Limits");
@@ -457,7 +443,6 @@ public class AppTimeLimitController {
                pw.println();
                pw.print("    currentForegroundedPackage=");
                pw.println(user.currentForegroundedPackage);
                pw.print("    lastBackgroundedPackage="); pw.println(user.lastBackgroundedPackage);
            }
        }
    }
Loading