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 {
|
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 int getAppStandbyBucket(String);
|
||||||
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
|
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 public int getUsageSource();
|
||||||
method @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES) public void onCarrierPrivilegedAppsChanged();
|
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);
|
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);
|
void reportUsageStop(in IBinder activity, String token, String callingPackage);
|
||||||
int getUsageSource();
|
int getUsageSource();
|
||||||
void forceUsageSourceSettingRead();
|
void forceUsageSourceSettingRead();
|
||||||
|
long getLastTimeAnyComponentUsed(String packageName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1250,4 +1250,33 @@ public final class UsageStatsManager {
|
|||||||
} catch (RemoteException re) {
|
} 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
|
@Test
|
||||||
public void testReportEvent_packageUsedEventNotTracked() {
|
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;
|
event.mPackage = TEST_PACKAGE_NAME;
|
||||||
mService.reportEvent(event);
|
mService.reportEvent(event);
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ import android.os.SystemProperties;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.AtomicFile;
|
import android.util.AtomicFile;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -109,8 +110,10 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service that collects, aggregates, and persists application usage data.
|
* 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();
|
private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
|
||||||
int mUsageSource;
|
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. */
|
/** Manages the standby state of apps. */
|
||||||
AppStandbyInternal mAppStandby;
|
AppStandbyInternal mAppStandby;
|
||||||
|
|
||||||
@@ -279,6 +287,9 @@ public class UsageStatsService extends SystemService implements
|
|||||||
getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
|
getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
|
||||||
null, mHandler);
|
null, mHandler);
|
||||||
|
|
||||||
|
mRealTimeSnapshot = SystemClock.elapsedRealtime();
|
||||||
|
mSystemTimeSnapshot = System.currentTimeMillis();
|
||||||
|
|
||||||
publishLocalService(UsageStatsManagerInternal.class, new LocalService());
|
publishLocalService(UsageStatsManagerInternal.class, new LocalService());
|
||||||
publishLocalService(AppStandbyInternal.class, mAppStandby);
|
publishLocalService(AppStandbyInternal.class, mAppStandby);
|
||||||
publishBinderServices();
|
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.
|
* Called by the Binder stub.
|
||||||
*/
|
*/
|
||||||
@@ -940,6 +973,12 @@ public class UsageStatsService extends SystemService implements
|
|||||||
Slog.w(TAG, "Failed to note usage stop", iae);
|
Slog.w(TAG, "Failed to note usage stop", iae);
|
||||||
}
|
}
|
||||||
break;
|
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);
|
final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
|
||||||
@@ -2094,6 +2133,16 @@ public class UsageStatsService extends SystemService implements
|
|||||||
public void forceUsageSourceSettingRead() {
|
public void forceUsageSourceSettingRead() {
|
||||||
readUsageSourceSetting();
|
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,
|
void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
|
||||||
|
|||||||
@@ -277,8 +277,11 @@ class UserUsageStatsService {
|
|||||||
+ eventToString(event.mEventType));
|
+ eventToString(event.mEventType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.mEventType != Event.USER_INTERACTION
|
||||||
|
&& event.mEventType != Event.APP_COMPONENT_USED) {
|
||||||
checkAndGetTimeLocked();
|
checkAndGetTimeLocked();
|
||||||
convertToSystemTimeLocked(event);
|
convertToSystemTimeLocked(event);
|
||||||
|
}
|
||||||
|
|
||||||
if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
|
if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
|
||||||
// Need to rollover
|
// Need to rollover
|
||||||
|
|||||||
Reference in New Issue
Block a user