Get UsageStats if no PackageUsage is available for boot dexopt filtering.
Bug: 17191977
Change-Id: I33e18459e49afa42b8e8218574a2434e5205a6da
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b79e157..6b046f2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -84,6 +84,8 @@
import android.app.IActivityManager;
import android.app.admin.IDevicePolicyManager;
import android.app.backup.IBackupManager;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -329,6 +331,7 @@
final boolean mFactoryTest;
final boolean mOnlyCore;
final boolean mLazyDexOpt;
+ final long mDexOptLRUThresholdInMills;
final DisplayMetrics mMetrics;
final int mDefParseFlags;
final String[] mSeparateProcesses;
@@ -1294,6 +1297,15 @@
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+ // TODO: add a property to control this?
+ long dexOptLRUThresholdInMinutes;
+ if (mLazyDexOpt) {
+ dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
+ } else {
+ dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
+ }
+ mDexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
+
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
@@ -4568,22 +4580,13 @@
// The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
// should do a full dexopt.
if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
- // TODO: add a property to control this?
- long dexOptLRUThresholdInMinutes;
- if (mLazyDexOpt) {
- dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
- } else {
- dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
- }
- long dexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
-
int total = pkgs.size();
int skipped = 0;
long now = System.currentTimeMillis();
for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
PackageParser.Package pkg = i.next();
long then = pkg.mLastPackageUsageTimeInMills;
- if (then + dexOptLRUThresholdInMills < now) {
+ if (then + mDexOptLRUThresholdInMills < now) {
if (DEBUG_DEXOPT) {
Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " +
((then == 0) ? "never" : new Date(then)));
@@ -13381,4 +13384,25 @@
return false;
}
}
+
+ public void getUsageStatsIfNoPackageUsageInfo() {
+ if (!mPackageUsage.isHistoricalPackageUsageAvailable()) {
+ UsageStatsManager usm = (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE);
+ if (usm == null) {
+ throw new IllegalStateException("UsageStatsManager must be initialized");
+ }
+ long now = System.currentTimeMillis();
+ Map<String, UsageStats> stats = usm.queryAndAggregateUsageStats(now - mDexOptLRUThresholdInMills, now);
+ for (Map.Entry<String, UsageStats> entry : stats.entrySet()) {
+ String packageName = entry.getKey();
+ PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ continue;
+ }
+ UsageStats usage = entry.getValue();
+ pkg.mLastPackageUsageTimeInMills = usage.getLastTimeUsed();
+ mPackageUsage.mIsHistoricalPackageUsageAvailable = true;
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6009ffd..d7f6130 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -374,6 +374,8 @@
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));
+ // Update after UsageStatsService is available, needed before performBootDexOpt.
+ mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();
// Tracks whether the updatable WebView is in a ready state and watches for update installs.
mSystemServiceManager.startService(WebViewUpdateService.class);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 2ed9745..7ff246a 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -38,6 +38,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -349,8 +350,12 @@
private class BinderService extends IUsageStatsManager.Stub {
private boolean hasPermission(String callingPackage) {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == Process.SYSTEM_UID) {
+ return true;
+ }
final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
- Binder.getCallingUid(), callingPackage);
+ callingUid, callingPackage);
if (mode == AppOpsManager.MODE_DEFAULT) {
// The default behavior here is to check if PackageManager has given the app
// permission.