Implement issue #16330060: Inform ActivityManager about WebView...

...state changes.

Add a new API to tell the activity manager about a new dependency
one process has on another package.  Start using it already for
when apps is Context.createPackageContext() to load code from another
app.

Also do some work on getting the monitoring of proc/uid states
in shape so it can be used by unundled code, along with an
AppImportanceMonitor class for doing so.

Some small fixes and additions to VoiceInteractionService.

Improve handling of unaccounted/overcounted battery use so that
they aren't shown to the user unless they are significant.

Change-Id: I22dd79a73f4e70103d3f8964494aebc8a31f971c
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0f55b0f..8b7e0d6 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4715,6 +4715,28 @@
         }
     }
 
+    @Override
+    public void addPackageDependency(String packageName) {
+        synchronized (this) {
+            int callingPid = Binder.getCallingPid();
+            if (callingPid == Process.myPid()) {
+                //  Yeah, um, no.
+                Slog.w(TAG, "Can't addPackageDependency on system process");
+                return;
+            }
+            ProcessRecord proc;
+            synchronized (mPidsSelfLocked) {
+                proc = mPidsSelfLocked.get(Binder.getCallingPid());
+            }
+            if (proc != null) {
+                if (proc.pkgDeps == null) {
+                    proc.pkgDeps = new ArraySet<String>(1);
+                }
+                proc.pkgDeps.add(packageName);
+            }
+        }
+    }
+
     /*
      * The pkg name and app id have to be specified.
      */
@@ -4911,7 +4933,6 @@
         // Remove all processes this package may have touched: all with the
         // same UID (except for the system or root user), and all whose name
         // matches the package name.
-        final String procNamePrefix = packageName != null ? (packageName + ":") : null;
         final int NP = mProcessNames.getMap().size();
         for (int ip=0; ip<NP; ip++) {
             SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
@@ -4947,13 +4968,15 @@
                 // that match it.  We need to qualify this by the processes
                 // that are running under the specified app and user ID.
                 } else {
-                    if (UserHandle.getAppId(app.uid) != appId) {
+                    final boolean isDep = app.pkgDeps != null
+                            && app.pkgDeps.contains(packageName);
+                    if (!isDep && UserHandle.getAppId(app.uid) != appId) {
                         continue;
                     }
                     if (userId != UserHandle.USER_ALL && app.userId != userId) {
                         continue;
                     }
-                    if (!app.pkgList.containsKey(packageName)) {
+                    if (!app.pkgList.containsKey(packageName) && !isDep) {
                         continue;
                     }
                 }
@@ -11030,30 +11053,15 @@
         return errList;
     }
 
-    static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
-        if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
-            if (currApp != null) {
-                currApp.lru = adj - ProcessList.CACHED_APP_MIN_ADJ + 1;
-            }
-            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-        } else if (adj >= ProcessList.SERVICE_B_ADJ) {
-            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
-        } else if (adj >= ProcessList.HOME_APP_ADJ) {
-            if (currApp != null) {
-                currApp.lru = 0;
-            }
-            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-        } else if (adj >= ProcessList.SERVICE_ADJ) {
-            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
-        } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
-            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
-        } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
-            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
-        } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
-            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+    static int procStateToImportance(int procState, int memAdj,
+            ActivityManager.RunningAppProcessInfo currApp) {
+        int imp = ActivityManager.RunningAppProcessInfo.procStateToImportance(procState);
+        if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
+            currApp.lru = memAdj;
         } else {
-            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+            currApp.lru = 0;
         }
+        return imp;
     }
 
     private void fillInProcMemInfo(ProcessRecord app,
@@ -11071,7 +11079,8 @@
         }
         outInfo.lastTrimLevel = app.trimMemoryLevel;
         int adj = app.curAdj;
-        outInfo.importance = oomAdjToImportance(adj, outInfo);
+        int procState = app.curProcState;
+        outInfo.importance = procStateToImportance(procState, adj, outInfo);
         outInfo.importanceReasonCode = app.adjTypeCode;
         outInfo.processState = app.curProcState;
     }
@@ -11098,8 +11107,9 @@
                     fillInProcMemInfo(app, currApp);
                     if (app.adjSource instanceof ProcessRecord) {
                         currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
-                        currApp.importanceReasonImportance = oomAdjToImportance(
-                                app.adjSourceOom, null);
+                        currApp.importanceReasonImportance =
+                                ActivityManager.RunningAppProcessInfo.procStateToImportance(
+                                        app.adjSourceProcState);
                     } else if (app.adjSource instanceof ActivityRecord) {
                         ActivityRecord r = (ActivityRecord)app.adjSource;
                         if (r.app != null) currApp.importanceReasonPid = r.app.pid;
@@ -15615,7 +15625,7 @@
                             app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                     .REASON_SERVICE_IN_USE;
                             app.adjSource = cr.binding.client;
-                            app.adjSourceOom = clientAdj;
+                            app.adjSourceProcState = clientProcState;
                             app.adjTarget = s.name;
                         }
                     }
@@ -15636,7 +15646,7 @@
                             app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                     .REASON_SERVICE_IN_USE;
                             app.adjSource = a;
-                            app.adjSourceOom = adj;
+                            app.adjSourceProcState = procState;
                             app.adjTarget = s.name;
                         }
                     }
@@ -15681,7 +15691,7 @@
                     app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                             .REASON_PROVIDER_IN_USE;
                     app.adjSource = client;
-                    app.adjSourceOom = clientAdj;
+                    app.adjSourceProcState = clientProcState;
                     app.adjTarget = cpr.name;
                 }
                 if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index a20be73..b33f7b7 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -55,6 +55,7 @@
     // List of packages running in the process
     final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList
             = new ArrayMap<String, ProcessStats.ProcessStateHolder>();
+    ArraySet<String> pkgDeps;   // additional packages we have a dependency on
     IApplicationThread thread;  // the actual proc...  may be null only if
                                 // 'persistent' is true (in which case we
                                 // are in the process of launching the app)
@@ -124,7 +125,7 @@
     String adjType;             // Debugging: primary thing impacting oom_adj.
     int adjTypeCode;            // Debugging: adj code to report to app.
     Object adjSource;           // Debugging: option dependent object.
-    int adjSourceOom;           // Debugging: oom_adj of adjSource's process.
+    int adjSourceProcState;     // Debugging: proc state of adjSource's process.
     Object adjTarget;           // Debugging: target component impacting oom_adj.
     
     // contains HistoryRecord objects
@@ -195,6 +196,14 @@
             pw.print(pkgList.keyAt(i));
         }
         pw.println("}");
+        if (pkgDeps != null) {
+            pw.print(prefix); pw.print("packageDependencies={");
+            for (int i=0; i<pkgDeps.size(); i++) {
+                if (i > 0) pw.print(", ");
+                pw.print(pkgDeps.valueAt(i));
+            }
+            pw.println("}");
+        }
         pw.print(prefix); pw.print("compat="); pw.println(compat);
         if (instrumentationClass != null || instrumentationProfileFile != null
                 || instrumentationArguments != null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 1f40c26..54af5d4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -87,6 +87,10 @@
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized (mLock) {
                 mService = IVoiceInteractionService.Stub.asInterface(service);
+                try {
+                    mService.ready();
+                } catch (RemoteException e) {
+                }
             }
         }