Merge "Create package-level last time usage stats for app hibernation" into sc-dev

This commit is contained in:
Zhen Zhang
2021-03-31 09:04:50 +00:00
committed by Android (Google) Code Review
6 changed files with 88 additions and 3 deletions

View File

@@ -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);

View File

@@ -67,4 +67,5 @@ interface IUsageStatsManager {
void reportUsageStop(in IBinder activity, String token, String callingPackage);
int getUsageSource();
void forceUsageSourceSettingRead();
long getLastTimeAnyComponentUsed(String packageName);
}

View File

@@ -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();
}
}
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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