summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSudheer Shanka <sudheersai@google.com>2022-03-15 15:35:17 -0700
committerSudheer Shanka <sudheersai@google.com>2022-03-23 18:46:50 +0000
commit9ef2c906e80f42e1e63b3f2003fd649eb4969d6a (patch)
tree91280e9b8d3bb54e126108792436deec51a8a0dd
parent352d8d7abee0f1ee215ea7be3580752e6eda77ff (diff)
Add "clear-last-used-timestamps" command to usagestats service.
Bug: 206518483 Test: atest tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java Change-Id: Ieeedb17182ea93e162e2d7fb2d53169f2cc70e3a
-rw-r--r--apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java3
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java11
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java7
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java13
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsShellCommand.java79
5 files changed, 113 insertions, 0 deletions
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index f822a188c99c..56811076e013 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -245,4 +245,7 @@ public interface AppStandbyInternal {
*/
@Nullable
String getAppStandbyConstant(@NonNull String key);
+
+ /** Clears the last used timestamps data for the given {@code packageName}. */
+ void clearLastUsedTimestampsForTest(@NonNull String packageName, @UserIdInt int userId);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index 2e3b377d08a5..7db358c816c5 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -686,6 +686,17 @@ public class AppIdleHistory {
Integer.toString(userId)), APP_IDLE_FILENAME);
}
+ void clearLastUsedTimestamps(String packageName, int userId) {
+ ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
+ AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
+ SystemClock.elapsedRealtime(), false /* create */);
+ if (appUsageHistory != null) {
+ appUsageHistory.lastUsedByUserElapsedTime = Integer.MIN_VALUE;
+ appUsageHistory.lastUsedElapsedTime = Integer.MIN_VALUE;
+ appUsageHistory.lastUsedScreenTime = Integer.MIN_VALUE;
+ }
+ }
+
/**
* Check if App Idle File exists on disk
* @param userId
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 502913063a00..75c0a933adea 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -1857,6 +1857,13 @@ public class AppStandbyController
}
@Override
+ public void clearLastUsedTimestampsForTest(@NonNull String packageName, @UserIdInt int userId) {
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.clearLastUsedTimestamps(packageName, userId);
+ }
+ }
+
+ @Override
public void flushToDisk() {
synchronized (mAppIdleLock) {
mAppIdleHistory.writeAppIdleTimes(mInjector.elapsedRealtime());
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 366ab0968bb8..da54c329d5be 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -79,6 +79,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -1982,6 +1983,10 @@ public class UsageStatsService extends SystemService implements
}
}
+ void clearLastUsedTimestamps(@NonNull String packageName, @UserIdInt int userId) {
+ mAppStandby.clearLastUsedTimestampsForTest(packageName, userId);
+ }
+
private final class BinderService extends IUsageStatsManager.Stub {
private boolean hasPermission(String callingPackage) {
@@ -2816,6 +2821,14 @@ public class UsageStatsService extends SystemService implements
}
return mAppStandby.getAppStandbyConstant(key);
}
+
+ @Override
+ public int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+ @NonNull String[] args) {
+ return new UsageStatsShellCommand(UsageStatsService.this).exec(this,
+ in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args);
+ }
}
void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
diff --git a/services/usage/java/com/android/server/usage/UsageStatsShellCommand.java b/services/usage/java/com/android/server/usage/UsageStatsShellCommand.java
new file mode 100644
index 000000000000..772b22a2b179
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/UsageStatsShellCommand.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.usage;
+
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+
+class UsageStatsShellCommand extends ShellCommand {
+ private final UsageStatsService mService;
+
+ UsageStatsShellCommand(UsageStatsService usageStatsService) {
+ mService = usageStatsService;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(null);
+ }
+ switch (cmd) {
+ case "clear-last-used-timestamps":
+ return runClearLastUsedTimestamps();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println("UsageStats service (usagestats) commands:");
+ pw.println("help");
+ pw.println(" Print this help text.");
+ pw.println();
+ pw.println("clear-last-used-timestamps PACKAGE_NAME [-u | --user USER_ID]");
+ pw.println(" Clears any existing usage data for the given package.");
+ pw.println();
+ }
+
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ private int runClearLastUsedTimestamps() {
+ final String packageName = getNextArgRequired();
+
+ int userId = UserHandle.USER_CURRENT;
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if ("-u".equals(opt) || "--user".equals(opt)) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ } else {
+ getErrPrintWriter().println("Error: unknown option: " + opt);
+ return -1;
+ }
+ }
+ if (userId == UserHandle.USER_CURRENT) {
+ userId = ActivityManager.getCurrentUser();
+ }
+
+ mService.clearLastUsedTimestamps(packageName, userId);
+ return 0;
+ }
+}