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

Commit e566f33a authored by Kweku Adams's avatar Kweku Adams
Browse files

Add SystemApi to change app launch time estimates.

An SystemApis that allow a prediction app to update app launch time
estimates.

Bug: 194532703
Test: atest CtsPermissionTestCases:AppIdleStatePermissionTest
Test: atest CtsPermission2TestCases
Change-Id: I0fde220fa038f7f1f4d543a8906e92ca625bf097
parent ef6564cb
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ package android {
    field public static final String CAPTURE_TV_INPUT = "android.permission.CAPTURE_TV_INPUT";
    field public static final String CAPTURE_VOICE_COMMUNICATION_OUTPUT = "android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT";
    field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
    field public static final String CHANGE_APP_LAUNCH_TIME_ESTIMATE = "android.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE";
    field public static final String CHANGE_DEVICE_IDLE_TEMP_WHITELIST = "android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST";
    field public static final String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
    field public static final String COMPANION_APPROVE_WIFI_CONNECTIONS = "android.permission.COMPANION_APPROVE_WIFI_CONNECTIONS";
@@ -1923,6 +1924,8 @@ package android.app.usage {
    method public void reportUsageStop(@NonNull android.app.Activity, @NonNull String);
    method @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) public void setAppStandbyBucket(String, int);
    method @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) public void setAppStandbyBuckets(java.util.Map<java.lang.String,java.lang.Integer>);
    method @RequiresPermission(android.Manifest.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE) public void setEstimatedLaunchTime(@NonNull String, long);
    method @RequiresPermission(android.Manifest.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE) public void setEstimatedLaunchTimes(@NonNull java.util.Map<java.lang.String,java.lang.Long>);
    method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void unregisterAppUsageLimitObserver(int);
    method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void unregisterAppUsageObserver(int);
    method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void unregisterUsageSessionObserver(int);
+72 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.CurrentTimeMillisLong;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * A pair of {package, estimated launch time} to denote the estimated launch time for a given
 * package.
 * Used as a vehicle of data across the binder IPC.
 *
 * @hide
 */
public final class AppLaunchEstimateInfo implements Parcelable {

    public final String packageName;
    @CurrentTimeMillisLong
    public final long estimatedLaunchTime;

    private AppLaunchEstimateInfo(Parcel in) {
        packageName = in.readString();
        estimatedLaunchTime = in.readLong();
    }

    public AppLaunchEstimateInfo(String packageName,
            @CurrentTimeMillisLong long estimatedLaunchTime) {
        this.packageName = packageName;
        this.estimatedLaunchTime = estimatedLaunchTime;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(packageName);
        dest.writeLong(estimatedLaunchTime);
    }

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

                @Override
                public AppLaunchEstimateInfo[] newArray(int size) {
                    return new AppLaunchEstimateInfo[size];
                }
            };
}
+2 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ interface IUsageStatsManager {
    void setAppStandbyBucket(String packageName, int bucket, int userId);
    ParceledListSlice getAppStandbyBuckets(String callingPackage, int userId);
    void setAppStandbyBuckets(in ParceledListSlice appBuckets, int userId);
    void setEstimatedLaunchTime(String packageName, long estimatedLaunchTime, int userId);
    void setEstimatedLaunchTimes(in ParceledListSlice appLaunchTimes, int userId);
    void registerAppUsageObserver(int observerId, in String[] packages, long timeLimitMs,
            in PendingIntent callback, String callingPackage);
    void unregisterAppUsageObserver(int observerId, String callingPackage);
+67 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.app.usage;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -771,6 +772,72 @@ public final class UsageStatsManager {
        }
    }

    /**
     * Changes an app's estimated launch time. An app is considered "launched" when a user opens
     * one of its {@link android.app.Activity Activities}. The provided time is persisted across
     * reboots and is used unless 1) the time is more than a week in the future and the platform
     * thinks the app will be launched sooner, 2) the estimated time has passed. Passing in
     * {@link Long#MAX_VALUE} effectively clears the previously set launch time for the app.
     *
     * @param packageName         The package name of the app to set the bucket for.
     * @param estimatedLaunchTime The next time the app is expected to be launched. Units are in
     *                            milliseconds since epoch (the same as
     *                            {@link System#currentTimeMillis()}).
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE)
    public void setEstimatedLaunchTime(@NonNull String packageName,
            @CurrentTimeMillisLong long estimatedLaunchTime) {
        if (packageName == null) {
            throw new NullPointerException("package name cannot be null");
        }
        if (estimatedLaunchTime <= 0) {
            throw new IllegalArgumentException("estimated launch time must be positive");
        }
        try {
            mService.setEstimatedLaunchTime(packageName, estimatedLaunchTime, mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Changes the estimated launch times for multiple apps at once. The map is keyed by the
     * package name and the value is the estimated launch time.
     *
     * @param estimatedLaunchTimes A map of package name to estimated launch time.
     * @see #setEstimatedLaunchTime(String, long)
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE)
    public void setEstimatedLaunchTimes(@NonNull Map<String, Long> estimatedLaunchTimes) {
        if (estimatedLaunchTimes == null) {
            throw new NullPointerException("estimatedLaunchTimes cannot be null");
        }
        final List<AppLaunchEstimateInfo> estimateList =
                new ArrayList<>(estimatedLaunchTimes.size());
        for (Map.Entry<String, Long> estimateEntry : estimatedLaunchTimes.entrySet()) {
            final String pkgName = estimateEntry.getKey();
            if (pkgName == null) {
                throw new NullPointerException("package name cannot be null");
            }
            final Long estimatedLaunchTime = estimateEntry.getValue();
            if (estimatedLaunchTime == null || estimatedLaunchTime <= 0) {
                throw new IllegalArgumentException("estimated launch time must be positive");
            }
            estimateList.add(new AppLaunchEstimateInfo(pkgName, estimatedLaunchTime));
        }
        final ParceledListSlice<AppLaunchEstimateInfo> slice =
                new ParceledListSlice<>(estimateList);
        try {
            mService.setEstimatedLaunchTimes(slice, mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide
     * Register an app usage limit observer that receives a callback on the provided intent when
+5 −0
Original line number Diff line number Diff line
@@ -4880,6 +4880,11 @@
    <permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
        android:protectionLevel="signature|privileged" />

    <!-- @hide @SystemApi Allows an application to change the estimated launch time of an app.
         <p>Not for use by third-party applications. -->
    <permission android:name="android.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE"
        android:protectionLevel="signature|privileged" />

    <!-- @hide @SystemApi Allows an application to temporarily allowlist an inactive app to
         access the network and acquire wakelocks.
         <p>Not for use by third-party applications. -->
Loading