1 package com.android.server.usage; 2 3 import android.annotation.CurrentTimeMillisLong; 4 import android.annotation.ElapsedRealtimeLong; 5 import android.annotation.NonNull; 6 import android.annotation.Nullable; 7 import android.annotation.UserIdInt; 8 import android.app.ActivityManager.ProcessState; 9 import android.app.usage.AppStandbyInfo; 10 import android.app.usage.UsageStatsManager.ForcedReasons; 11 import android.app.usage.UsageStatsManager.StandbyBuckets; 12 import android.content.Context; 13 import android.util.IndentingPrintWriter; 14 15 import java.io.PrintWriter; 16 import java.lang.reflect.Constructor; 17 import java.lang.reflect.InvocationTargetException; 18 import java.util.List; 19 import java.util.Set; 20 21 public interface AppStandbyInternal { 22 /** 23 * TODO AppStandbyController should probably be a binder service, and then we shouldn't need 24 * this method. 25 */ newAppStandbyController(ClassLoader loader, Context context)26 static AppStandbyInternal newAppStandbyController(ClassLoader loader, Context context) { 27 try { 28 final Class<?> clazz = Class.forName("com.android.server.usage.AppStandbyController", 29 true, loader); 30 final Constructor<?> ctor = clazz.getConstructor(Context.class); 31 return (AppStandbyInternal) ctor.newInstance(context); 32 } catch (NoSuchMethodException | InstantiationException 33 | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) { 34 throw new RuntimeException("Unable to instantiate AppStandbyController!", e); 35 } 36 } 37 38 /** 39 * Listener interface for notifications that an app's idle state changed. 40 */ 41 abstract static class AppIdleStateChangeListener { 42 43 /** Callback to inform listeners that the idle state has changed to a new bucket. */ onAppIdleStateChanged(String packageName, @UserIdInt int userId, boolean idle, int bucket, int reason)44 public abstract void onAppIdleStateChanged(String packageName, @UserIdInt int userId, 45 boolean idle, int bucket, int reason); 46 47 /** 48 * Callback to inform listeners that the parole state has changed. This means apps are 49 * allowed to do work even if they're idle or in a low bucket. 50 */ onParoleStateChanged(boolean isParoleOn)51 public void onParoleStateChanged(boolean isParoleOn) { 52 // No-op by default 53 } 54 55 /** 56 * Optional callback to inform the listener that the app has transitioned into 57 * an active state due to user interaction. 58 */ onUserInteractionStarted(String packageName, @UserIdInt int userId)59 public void onUserInteractionStarted(String packageName, @UserIdInt int userId) { 60 // No-op by default 61 } 62 63 /** 64 * Optional callback to inform the listener to give the app a temporary quota bump. 65 */ triggerTemporaryQuotaBump(String packageName, @UserIdInt int userId)66 public void triggerTemporaryQuotaBump(String packageName, @UserIdInt int userId) { 67 // No-op by default 68 } 69 } 70 onBootPhase(int phase)71 void onBootPhase(int phase); 72 postCheckIdleStates(int userId)73 void postCheckIdleStates(int userId); 74 75 /** 76 * We send a different message to check idle states once, otherwise we would end up 77 * scheduling a series of repeating checkIdleStates each time we fired off one. 78 */ postOneTimeCheckIdleStates()79 void postOneTimeCheckIdleStates(); 80 setLastJobRunTime(String packageName, int userId, long elapsedRealtime)81 void setLastJobRunTime(String packageName, int userId, long elapsedRealtime); 82 getTimeSinceLastJobRun(String packageName, int userId)83 long getTimeSinceLastJobRun(String packageName, int userId); 84 setEstimatedLaunchTime(String packageName, int userId, @CurrentTimeMillisLong long launchTimeMs)85 void setEstimatedLaunchTime(String packageName, int userId, 86 @CurrentTimeMillisLong long launchTimeMs); 87 88 /** 89 * Returns the saved estimated launch time for the app. Will return {@code Long#MAX_VALUE} if no 90 * value is saved. 91 */ 92 @CurrentTimeMillisLong getEstimatedLaunchTime(String packageName, int userId)93 long getEstimatedLaunchTime(String packageName, int userId); 94 95 /** 96 * Returns the time (in milliseconds) since the app was last interacted with by the user. 97 * This can be larger than the current elapsedRealtime, in case it happened before boot or 98 * a really large value if the app was never interacted with. 99 */ getTimeSinceLastUsedByUser(String packageName, int userId)100 long getTimeSinceLastUsedByUser(String packageName, int userId); 101 onUserRemoved(int userId)102 void onUserRemoved(int userId); 103 addListener(AppIdleStateChangeListener listener)104 void addListener(AppIdleStateChangeListener listener); 105 removeListener(AppIdleStateChangeListener listener)106 void removeListener(AppIdleStateChangeListener listener); 107 getAppId(String packageName)108 int getAppId(String packageName); 109 110 /** 111 * @see #isAppIdleFiltered(String, int, int, long) 112 */ isAppIdleFiltered(String packageName, int userId, long elapsedRealtime, boolean shouldObfuscateInstantApps)113 boolean isAppIdleFiltered(String packageName, int userId, long elapsedRealtime, 114 boolean shouldObfuscateInstantApps); 115 116 /** 117 * Checks if an app has been idle for a while and filters out apps that are excluded. 118 * It returns false if the current system state allows all apps to be considered active. 119 * This happens if the device is plugged in or otherwise temporarily allowed to make exceptions. 120 * Called by interface impls. 121 */ isAppIdleFiltered(String packageName, int appId, int userId, long elapsedRealtime)122 boolean isAppIdleFiltered(String packageName, int appId, int userId, 123 long elapsedRealtime); 124 125 /** 126 * @return true if currently app idle parole mode is on. 127 */ isInParole()128 boolean isInParole(); 129 getIdleUidsForUser(int userId)130 int[] getIdleUidsForUser(int userId); 131 setAppIdleAsync(String packageName, boolean idle, int userId)132 void setAppIdleAsync(String packageName, boolean idle, int userId); 133 134 @StandbyBuckets getAppStandbyBucket(String packageName, int userId, long elapsedRealtime, boolean shouldObfuscateInstantApps)135 int getAppStandbyBucket(String packageName, int userId, 136 long elapsedRealtime, boolean shouldObfuscateInstantApps); 137 getAppStandbyBuckets(int userId)138 List<AppStandbyInfo> getAppStandbyBuckets(int userId); 139 140 /** 141 * Changes an app's standby bucket to the provided value. The caller can only set the standby 142 * bucket for a different app than itself. 143 * If attempting to automatically place an app in the RESTRICTED bucket, use 144 * {@link #restrictApp(String, int, int)} instead. 145 */ setAppStandbyBucket(@onNull String packageName, int bucket, int userId, int callingUid, int callingPid)146 void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId, int callingUid, 147 int callingPid); 148 149 /** 150 * Changes the app standby bucket for multiple apps at once. 151 */ setAppStandbyBuckets(@onNull List<AppStandbyInfo> appBuckets, int userId, int callingUid, int callingPid)152 void setAppStandbyBuckets(@NonNull List<AppStandbyInfo> appBuckets, int userId, int callingUid, 153 int callingPid); 154 155 /** Return the lowest bucket this app can enter. */ 156 @StandbyBuckets getAppMinStandbyBucket(String packageName, int appId, int userId, boolean shouldObfuscateInstantApps)157 int getAppMinStandbyBucket(String packageName, int appId, int userId, 158 boolean shouldObfuscateInstantApps); 159 160 /** 161 * Return the bucketing reason code of the given app. 162 */ getAppStandbyBucketReason(@onNull String packageName, @UserIdInt int userId, @ElapsedRealtimeLong long elapsedRealtime)163 int getAppStandbyBucketReason(@NonNull String packageName, @UserIdInt int userId, 164 @ElapsedRealtimeLong long elapsedRealtime); 165 166 /** 167 * Puts the list of apps in the {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RARE} 168 * bucket. 169 * @param restoredApps the list of restored apps 170 */ restoreAppsToRare(@onNull Set<String> restoredApps, int userId)171 void restoreAppsToRare(@NonNull Set<String> restoredApps, int userId); 172 173 /** 174 * Put the specified app in the 175 * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} 176 * bucket. If it has been used by the user recently, the restriction will delayed until an 177 * appropriate time. 178 * 179 * @param restrictReason The restrictReason for restricting the app. Should be one of the 180 * UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_* reasons. 181 */ restrictApp(@onNull String packageName, int userId, @ForcedReasons int restrictReason)182 void restrictApp(@NonNull String packageName, int userId, 183 @ForcedReasons int restrictReason); 184 185 /** 186 * Put the specified app in the 187 * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} 188 * bucket. If it has been used by the user recently, the restriction will delayed 189 * until an appropriate time. This should only be used in cases where 190 * {@link #restrictApp(String, int, int)} is not sufficient. 191 * 192 * @param mainReason The main reason for restricting the app. Must be either {@link 193 * android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_SYSTEM} or 194 * {@link android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_USER}. 195 * Calls providing any other value will be ignored. 196 * @param restrictReason The restrictReason for restricting the app. Should be one of the 197 * UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_* reasons. 198 */ restrictApp(@onNull String packageName, int userId, int mainReason, @ForcedReasons int restrictReason)199 void restrictApp(@NonNull String packageName, int userId, int mainReason, 200 @ForcedReasons int restrictReason); 201 202 /** 203 * Unrestrict an app if there is no other reason to restrict it. 204 * 205 * <p> 206 * The {@code prevMainReasonRestrict} and {@code prevSubReasonRestrict} are the previous 207 * reasons of why it was restricted, but the caller knows that these conditions are not true 208 * anymore; therefore if there is no other reasons to restrict it (as there could bemultiple 209 * reasons to restrict it), lift the restriction. 210 * </p> 211 * 212 * @param packageName The package name of the app. 213 * @param userId The user id that this app runs in. 214 * @param prevMainReasonRestrict The main reason that why it was restricted, must be either 215 * {@link android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_SYSTEM} 216 * or {@link android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_USER}. 217 * @param prevSubReasonRestrict The subreason that why it was restricted before. 218 * @param mainReasonUnrestrict The main reason that why it could be unrestricted now. 219 * @param subReasonUnrestrict The subreason that why it could be unrestricted now. 220 */ maybeUnrestrictApp(@onNull String packageName, int userId, int prevMainReasonRestrict, int prevSubReasonRestrict, int mainReasonUnrestrict, int subReasonUnrestrict)221 void maybeUnrestrictApp(@NonNull String packageName, int userId, int prevMainReasonRestrict, 222 int prevSubReasonRestrict, int mainReasonUnrestrict, int subReasonUnrestrict); 223 addActiveDeviceAdmin(String adminPkg, int userId)224 void addActiveDeviceAdmin(String adminPkg, int userId); 225 setActiveAdminApps(Set<String> adminPkgs, int userId)226 void setActiveAdminApps(Set<String> adminPkgs, int userId); 227 setAdminProtectedPackages(Set<String> packageNames, int userId)228 void setAdminProtectedPackages(Set<String> packageNames, int userId); 229 230 /** 231 * @return {@code true} if the given package is an active device admin app. 232 */ isActiveDeviceAdmin(String packageName, int userId)233 boolean isActiveDeviceAdmin(String packageName, int userId); 234 onAdminDataAvailable()235 void onAdminDataAvailable(); 236 clearCarrierPrivilegedApps()237 void clearCarrierPrivilegedApps(); 238 flushToDisk()239 void flushToDisk(); 240 initializeDefaultsForSystemApps(int userId)241 void initializeDefaultsForSystemApps(int userId); 242 postReportContentProviderUsage(String name, String packageName, int userId)243 void postReportContentProviderUsage(String name, String packageName, int userId); 244 postReportSyncScheduled(String packageName, int userId, boolean exempted)245 void postReportSyncScheduled(String packageName, int userId, boolean exempted); 246 postReportExemptedSyncStart(String packageName, int userId)247 void postReportExemptedSyncStart(String packageName, int userId); 248 dumpUsers(IndentingPrintWriter idpw, int[] userIds, List<String> pkgs)249 void dumpUsers(IndentingPrintWriter idpw, int[] userIds, List<String> pkgs); 250 dumpState(String[] args, PrintWriter pw)251 void dumpState(String[] args, PrintWriter pw); 252 isAppIdleEnabled()253 boolean isAppIdleEnabled(); 254 255 /** 256 * Returns the duration (in millis) for the window where events occurring will be 257 * considered as broadcast response, starting from the point when an app receives 258 * a broadcast. 259 */ getBroadcastResponseWindowDurationMs()260 long getBroadcastResponseWindowDurationMs(); 261 262 /** 263 * Returns the process state threshold that should be used for deciding whether or not an app 264 * is in the background in the context of recording broadcast response stats. Apps whose 265 * process state is higher than this threshold state should be considered to be in background. 266 */ 267 @ProcessState getBroadcastResponseFgThresholdState()268 int getBroadcastResponseFgThresholdState(); 269 270 /** 271 * Returns the duration within which any broadcasts occurred will be treated as one broadcast 272 * session. 273 */ getBroadcastSessionsDurationMs()274 long getBroadcastSessionsDurationMs(); 275 276 /** 277 * Returns the duration within which any broadcasts occurred (with a corresponding response 278 * event) will be treated as one broadcast session. This similar to 279 * {@link #getBroadcastSessionsDurationMs()}, except that this duration will be used to group 280 * only broadcasts that have a corresponding response event into sessions. 281 */ getBroadcastSessionsWithResponseDurationMs()282 long getBroadcastSessionsWithResponseDurationMs(); 283 284 /** 285 * Returns {@code true} if the response event should be attributed to all the broadcast 286 * sessions that occurred within the broadcast response window and {@code false} if the 287 * response event should be attributed to only the earliest broadcast session within the 288 * broadcast response window. 289 */ shouldNoteResponseEventForAllBroadcastSessions()290 boolean shouldNoteResponseEventForAllBroadcastSessions(); 291 292 /** 293 * Returns the list of roles whose holders are exempted from the requirement of starting 294 * a response event after receiving a broadcast. 295 */ 296 @NonNull getBroadcastResponseExemptedRoles()297 List<String> getBroadcastResponseExemptedRoles(); 298 299 /** 300 * Returns the list of permissions whose holders are exempted from the requirement of starting 301 * a response event after receiving a broadcast. 302 */ 303 @NonNull getBroadcastResponseExemptedPermissions()304 List<String> getBroadcastResponseExemptedPermissions(); 305 306 /** 307 * Return the last known value corresponding to the {@code key} from 308 * {@link android.provider.DeviceConfig#NAMESPACE_APP_STANDBY} in AppStandbyController. 309 */ 310 @Nullable getAppStandbyConstant(@onNull String key)311 String getAppStandbyConstant(@NonNull String key); 312 313 /** Clears the last used timestamps data for the given {@code packageName}. */ clearLastUsedTimestampsForTest(@onNull String packageName, @UserIdInt int userId)314 void clearLastUsedTimestampsForTest(@NonNull String packageName, @UserIdInt int userId); 315 } 316