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

Commit 7ce974c2 authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Add APIs for querying broadcast response stats.

Bug: 206518114
Test: atest tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
CTS-Coverage-Bug: 206518114
Change-Id: Idcefc143215a372a7bd786fcb2208a7c26f2f7e2
parent 6ec5f7fd
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -2161,6 +2161,18 @@ package android.app.time {
package android.app.usage {
  public final class BroadcastResponseStats implements android.os.Parcelable {
    ctor public BroadcastResponseStats(@NonNull String);
    method public int describeContents();
    method @IntRange(from=0) public int getBroadcastsDispatchedCount();
    method @IntRange(from=0) public int getNotificationsCancelledCount();
    method @IntRange(from=0) public int getNotificationsPostedCount();
    method @IntRange(from=0) public int getNotificationsUpdatedCount();
    method @NonNull public String getPackageName();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.BroadcastResponseStats> CREATOR;
  }
  public final class CacheQuotaHint implements android.os.Parcelable {
    ctor public CacheQuotaHint(@NonNull android.app.usage.CacheQuotaHint.Builder);
    method public int describeContents();
@@ -2216,11 +2228,13 @@ package android.app.usage {
  }
  public final class UsageStatsManager {
    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void clearBroadcastResponseStats(@NonNull String, @IntRange(from=1) long);
    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String);
    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
    method @RequiresPermission(allOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long getLastTimeAnyComponentUsed(@NonNull String);
    method public int getUsageSource();
    method @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES) public void onCarrierPrivilegedAppsChanged();
    method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public android.app.usage.BroadcastResponseStats queryBroadcastResponseStats(@NonNull String, @IntRange(from=1) long);
    method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
    method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
    method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app.usage;

parcelable BroadcastResponseStats;
 No newline at end of file
+186 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app.usage;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.BroadcastOptions;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * Class containing a collection of stats related to response events started from an app
 * after receiving a broadcast.
 *
 * @hide
 */
@SystemApi
public final class BroadcastResponseStats implements Parcelable {
    private final String mPackageName;
    private int mBroadcastsDispatchedCount;
    private int mNotificationsPostedCount;
    private int mNotificationsUpdatedCount;
    private int mNotificationsCancelledCount;

    public BroadcastResponseStats(@NonNull String packageName) {
        mPackageName = packageName;
    }

    private BroadcastResponseStats(@NonNull Parcel in) {
        mPackageName = in.readString8();
        mBroadcastsDispatchedCount = in.readInt();
        mNotificationsPostedCount = in.readInt();
        mNotificationsUpdatedCount = in.readInt();
        mNotificationsCancelledCount = in.readInt();
    }

    /**
     * @return the name of the package that the stats in this object correspond to.
     */
    @NonNull
    public String getPackageName() {
        return mPackageName;
    }

    /**
     * Returns the total number of broadcasts that were dispatched to the app by the caller.
     *
     * <b> Note that the returned count will only include the broadcasts that the caller explicitly
     * requested to record using
     * {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
     *
     * @return the total number of broadcasts that were dispatched to the app.
     */
    @IntRange(from = 0)
    public int getBroadcastsDispatchedCount() {
        return mBroadcastsDispatchedCount;
    }

    /**
     * Returns the total number of notifications posted by the app soon after receiving a
     * broadcast.
     *
     * <b> Note that the returned count will only include the notifications that correspond to the
     * broadcasts that the caller explicitly requested to record using
     * {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
     *
     * @return the total number of notifications posted by the app soon after receiving
     *         a broadcast.
     */
    @IntRange(from = 0)
    public int getNotificationsPostedCount() {
        return mNotificationsPostedCount;
    }

    /**
     * Returns the total number of notifications updated by the app soon after receiving a
     * broadcast.
     *
     * <b> Note that the returned count will only include the notifications that correspond to the
     * broadcasts that the caller explicitly requested to record using
     * {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
     *
     * @return the total number of notifications updated by the app soon after receiving
     *         a broadcast.
     */
    @IntRange(from = 0)
    public int getNotificationsUpdatedCount() {
        return mNotificationsUpdatedCount;
    }

    /**
     * Returns the total number of notifications cancelled by the app soon after receiving a
     * broadcast.
     *
     * <b> Note that the returned count will only include the notifications that correspond to the
     * broadcasts that the caller explicitly requested to record using
     * {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
     *
     * @return the total number of notifications cancelled by the app soon after receiving
     *         a broadcast.
     */
    @IntRange(from = 0)
    public int getNotificationsCancelledCount() {
        return mNotificationsCancelledCount;
    }

    /** @hide */
    public void incrementBroadcastsDispatchedCount(@IntRange(from = 0) int count) {
        mBroadcastsDispatchedCount += count;
    }

    /** @hide */
    public void incrementNotificationsPostedCount(@IntRange(from = 0) int count) {
        mNotificationsPostedCount += count;
    }

    /** @hide */
    public void incrementNotificationsUpdatedCount(@IntRange(from = 0) int count) {
        mNotificationsUpdatedCount += count;
    }

    /** @hide */
    public void incrementNotificationsCancelledCount(@IntRange(from = 0) int count) {
        mNotificationsCancelledCount += count;
    }

    /** @hide */
    public void addCounts(@NonNull BroadcastResponseStats stats) {
        incrementBroadcastsDispatchedCount(stats.getBroadcastsDispatchedCount());
        incrementNotificationsPostedCount(stats.getNotificationsPostedCount());
        incrementNotificationsUpdatedCount(stats.getNotificationsUpdatedCount());
        incrementNotificationsCancelledCount(stats.getNotificationsCancelledCount());
    }

    @Override
    public @NonNull String toString() {
        return "stats {"
                + "broadcastsSent=" + mBroadcastsDispatchedCount
                + ",notificationsPosted=" + mNotificationsPostedCount
                + ",notificationsUpdated=" + mNotificationsUpdatedCount
                + ",notificationsCancelled=" + mNotificationsCancelledCount
                + "}";
    }

    @Override
    public @ContentsFlags int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
        dest.writeString8(mPackageName);
        dest.writeInt(mBroadcastsDispatchedCount);
        dest.writeInt(mNotificationsPostedCount);
        dest.writeInt(mNotificationsUpdatedCount);
        dest.writeInt(mNotificationsCancelledCount);
    }

    public static final @NonNull Creator<BroadcastResponseStats> CREATOR =
            new Creator<BroadcastResponseStats>() {
                @Override
                public @NonNull BroadcastResponseStats createFromParcel(@NonNull Parcel source) {
                    return new BroadcastResponseStats(source);
                }

                @Override
                public @NonNull BroadcastResponseStats[] newArray(int size) {
                    return new BroadcastResponseStats[size];
                }
            };
}
+7 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app.usage;

import android.app.PendingIntent;
import android.app.usage.BroadcastResponseStats;
import android.app.usage.UsageEvents;
import android.content.pm.ParceledListSlice;

@@ -71,4 +72,10 @@ interface IUsageStatsManager {
    int getUsageSource();
    void forceUsageSourceSettingRead();
    long getLastTimeAnyComponentUsed(String packageName, String callingPackage);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
    BroadcastResponseStats queryBroadcastResponseStats(
            String packageName, long id, String callingPackage, int userId);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
    void clearBroadcastResponseStats(String packageName, long id, String callingPackage,
            int userId);
}
+63 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.app.usage;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -26,6 +27,7 @@ import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UserHandleAware;
import android.app.Activity;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -1383,4 +1385,65 @@ public final class UsageStatsManager {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Returns the broadcast response stats since the last boot corresponding to
     * {@code packageName} and {@code id}.
     *
     * <p>Broadcast response stats will include the aggregated data of what actions an app took upon
     * receiving a broadcast. This data will consider the broadcasts that the caller sent to
     * {@code packageName} and explicitly requested to record the response events using
     * {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
     *
     * @param packageName The name of the package that the caller wants to query for.
     * @param id The ID corresponding to the broadcasts that the caller wants to query for. This is
     *           the ID the caller specifies when requesting a broadcast response event to be
     *           recorded using {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
     *
     * @return the broadcast response stats corresponding to {@code packageName} and {@code id}.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
    @UserHandleAware
    @NonNull
    public BroadcastResponseStats queryBroadcastResponseStats(
            @NonNull String packageName, @IntRange(from = 1) long id) {
        try {
            return mService.queryBroadcastResponseStats(packageName, id,
                    mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Clears the broadcast response stats corresponding to {@code packageName} and {@code id}.
     *
     * When a caller uses this API, stats related to the events occurring till that point will be
     * cleared and subsequent calls to {@link #queryBroadcastResponseStats(String, long)} will
     * return stats related to events occurring after this.
     *
     * @param packageName The name of the package that the caller wants to clear the data for.
     * @param id The ID corresponding to the broadcasts that the caller wants to clear the data for.
     *           This is the ID the caller specifies when requesting a broadcast response event
     *           to be recorded using
     *           {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
     *
     * @see #queryBroadcastResponseStats(String, long)
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
    @UserHandleAware
    public void clearBroadcastResponseStats(@NonNull String packageName,
            @IntRange(from = 1) long id) {
        try {
            mService.clearBroadcastResponseStats(packageName, id,
                    mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }
}
Loading