Merge "Create package-level last time usage stats for app hibernation" into sc-dev
This commit is contained in:
@@ -1847,6 +1847,7 @@ package android.app.usage {
|
||||
public final class UsageStatsManager {
|
||||
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 @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);
|
||||
|
||||
@@ -67,4 +67,5 @@ interface IUsageStatsManager {
|
||||
void reportUsageStop(in IBinder activity, String token, String callingPackage);
|
||||
int getUsageSource();
|
||||
void forceUsageSourceSettingRead();
|
||||
long getLastTimeAnyComponentUsed(String packageName);
|
||||
}
|
||||
|
||||
@@ -1250,4 +1250,33 @@ public final class UsageStatsManager {
|
||||
} catch (RemoteException re) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last time a package is used by any users including explicit user interaction and
|
||||
* component usage, measured in milliseconds since the epoch and truncated to the boundary of
|
||||
* last day before the exact time. For packages that are never used, the time will be the epoch.
|
||||
* <p> Note that this usage stats is user-agnostic. </p>
|
||||
* <p>
|
||||
* Also note that component usage is only reported for component bindings (e.g. broadcast
|
||||
* receiver, service, content provider) and only when such a binding would cause an app to leave
|
||||
* the stopped state.
|
||||
* See {@link UsageEvents.Event.USER_INTERACTION}, {@link UsageEvents.Event.APP_COMPONENT_USED}.
|
||||
* </p>
|
||||
*
|
||||
* @param packageName The name of the package to be queried.
|
||||
* @return last time the queried package is used since the epoch.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(allOf = {
|
||||
android.Manifest.permission.INTERACT_ACROSS_USERS,
|
||||
android.Manifest.permission.PACKAGE_USAGE_STATS})
|
||||
public long getLastTimeAnyComponentUsed(@NonNull String packageName) {
|
||||
// TODO(b/183462940): This usage data is not persisted to disk yet.
|
||||
try {
|
||||
return mService.getLastTimeAnyComponentUsed(packageName);
|
||||
} catch (RemoteException re) {
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,9 @@ public class UserUsageStatsServiceTest {
|
||||
|
||||
@Test
|
||||
public void testReportEvent_packageUsedEventNotTracked() {
|
||||
Event event = new Event(APP_COMPONENT_USED, SystemClock.elapsedRealtime());
|
||||
// For APP_COMPONENT_USED event, the time stamp should have been converted to current time
|
||||
// before reported here.
|
||||
Event event = new Event(APP_COMPONENT_USED, System.currentTimeMillis());
|
||||
event.mPackage = TEST_PACKAGE_NAME;
|
||||
mService.reportEvent(event);
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Slog;
|
||||
@@ -109,8 +110,10 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A service that collects, aggregates, and persists application usage data.
|
||||
@@ -166,6 +169,11 @@ public class UsageStatsService extends SystemService implements
|
||||
private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
|
||||
int mUsageSource;
|
||||
|
||||
private long mRealTimeSnapshot;
|
||||
private long mSystemTimeSnapshot;
|
||||
// A map storing last time global usage of packages, measured in milliseconds since the epoch.
|
||||
private final Map<String, Long> mLastTimeComponentUsedGlobal = new ArrayMap<>();
|
||||
|
||||
/** Manages the standby state of apps. */
|
||||
AppStandbyInternal mAppStandby;
|
||||
|
||||
@@ -279,6 +287,9 @@ public class UsageStatsService extends SystemService implements
|
||||
getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
|
||||
null, mHandler);
|
||||
|
||||
mRealTimeSnapshot = SystemClock.elapsedRealtime();
|
||||
mSystemTimeSnapshot = System.currentTimeMillis();
|
||||
|
||||
publishLocalService(UsageStatsManagerInternal.class, new LocalService());
|
||||
publishLocalService(AppStandbyInternal.class, mAppStandby);
|
||||
publishBinderServices();
|
||||
@@ -803,6 +814,28 @@ public class UsageStatsService extends SystemService implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assuming the event's timestamp is measured in milliseconds since boot,
|
||||
* convert it to a system wall time. System and real time snapshots are updated before
|
||||
* conversion.
|
||||
*/
|
||||
private void convertToSystemTimeLocked(Event event) {
|
||||
final long actualSystemTime = System.currentTimeMillis();
|
||||
if (ENABLE_TIME_CHANGE_CORRECTION) {
|
||||
final long actualRealtime = SystemClock.elapsedRealtime();
|
||||
final long expectedSystemTime =
|
||||
(actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
|
||||
final long diffSystemTime = actualSystemTime - expectedSystemTime;
|
||||
if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
|
||||
// The time has changed.
|
||||
Slog.i(TAG, "Time changed in by " + (diffSystemTime / 1000) + " seconds");
|
||||
mRealTimeSnapshot = actualRealtime;
|
||||
mSystemTimeSnapshot = actualSystemTime;
|
||||
}
|
||||
}
|
||||
event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the Binder stub.
|
||||
*/
|
||||
@@ -940,6 +973,12 @@ public class UsageStatsService extends SystemService implements
|
||||
Slog.w(TAG, "Failed to note usage stop", iae);
|
||||
}
|
||||
break;
|
||||
case Event.USER_INTERACTION:
|
||||
// Fall through
|
||||
case Event.APP_COMPONENT_USED:
|
||||
convertToSystemTimeLocked(event);
|
||||
mLastTimeComponentUsedGlobal.put(event.mPackage, event.mTimeStamp);
|
||||
break;
|
||||
}
|
||||
|
||||
final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
|
||||
@@ -2094,6 +2133,16 @@ public class UsageStatsService extends SystemService implements
|
||||
public void forceUsageSourceSettingRead() {
|
||||
readUsageSourceSetting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastTimeAnyComponentUsed(String packageName) {
|
||||
synchronized (mLock) {
|
||||
// Truncate the returned milliseconds to the boundary of the last day before exact
|
||||
// time for privacy reasons.
|
||||
return mLastTimeComponentUsedGlobal.getOrDefault(packageName, 0L)
|
||||
/ TimeUnit.DAYS.toMillis(1) * TimeUnit.DAYS.toMillis(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
|
||||
|
||||
@@ -277,8 +277,11 @@ class UserUsageStatsService {
|
||||
+ eventToString(event.mEventType));
|
||||
}
|
||||
|
||||
checkAndGetTimeLocked();
|
||||
convertToSystemTimeLocked(event);
|
||||
if (event.mEventType != Event.USER_INTERACTION
|
||||
&& event.mEventType != Event.APP_COMPONENT_USED) {
|
||||
checkAndGetTimeLocked();
|
||||
convertToSystemTimeLocked(event);
|
||||
}
|
||||
|
||||
if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
|
||||
// Need to rollover
|
||||
|
||||
Reference in New Issue
Block a user