auto import from //depot/cupcake/@136594
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 141569e..2ede783 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -263,6 +263,11 @@
     final int HIDDEN_APP_MAX_ADJ;
     static int HIDDEN_APP_MIN_ADJ;
 
+    // This is a process holding the home application -- we want to try
+    // avoiding killing it, even if it would normally be in the background,
+    // because the user interacts with it so much.
+    final int HOME_APP_ADJ;
+
     // This is a process holding a secondary server -- killing it will not
     // have much of an impact as far as the user is concerned. Value set in
     // system/rootdir/init.rc on startup.
@@ -290,6 +295,7 @@
     // Corresponding memory levels for above adjustments.
     final int EMPTY_APP_MEM;
     final int HIDDEN_APP_MEM;
+    final int HOME_APP_MEM;
     final int SECONDARY_SERVER_MEM;
     final int VISIBLE_APP_MEM;
     final int FOREGROUND_APP_MEM;
@@ -487,6 +493,12 @@
             = new ArrayList<ProcessRecord>();
 
     /**
+     * This is the process holding what we currently consider to be
+     * the "home" activity.
+     */
+    private ProcessRecord mHomeProcess;
+    
+    /**
      * List of running activities, sorted by recent usage.
      * The first entry in the list is the least recently used.
      * It contains HistoryRecord objects.
@@ -871,6 +883,11 @@
                         Log.e(TAG, "App already has anr dialog: " + proc);
                         return;
                     }
+                    
+                    broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
+                            null, null, 0, null, null, null,
+                            false, false, MY_PID, Process.SYSTEM_UID);
+
                     Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
                             mContext, proc, (HistoryRecord)data.get("activity"));
                     d.show();
@@ -1267,6 +1284,8 @@
             Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
         SECONDARY_SERVER_ADJ =
             Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
+        HOME_APP_ADJ =
+            Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
         HIDDEN_APP_MIN_ADJ =
             Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
         CONTENT_PROVIDER_ADJ =
@@ -1280,6 +1299,8 @@
             Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
         SECONDARY_SERVER_MEM =
             Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
+        HOME_APP_MEM =
+            Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
         HIDDEN_APP_MEM =
             Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
         EMPTY_APP_MEM =
@@ -1548,6 +1569,9 @@
                         System.identityHashCode(r),
                         r.task.taskId, r.shortComponentName);
             }
+            if (r.isHomeActivity) {
+                mHomeProcess = app;
+            }
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
                     r.info, r.icicle, results, newIntents, !andResume,
                     isNextTransitionForward());
@@ -2188,7 +2212,7 @@
                 if (app == null || app.instrumentationClass == null) {
                     intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                     startActivityLocked(null, intent, null, null, 0, aInfo,
-                            null, null, 0, 0, 0, false);
+                            null, null, 0, 0, 0, false, false);
                 }
             }
             return true;
@@ -2669,7 +2693,8 @@
             Uri[] grantedUriPermissions,
             int grantedMode, ActivityInfo aInfo, IBinder resultTo,
             String resultWho, int requestCode,
-            int callingPid, int callingUid, boolean onlyIfNeeded) {
+            int callingPid, int callingUid, boolean onlyIfNeeded,
+            boolean componentSpecified) {
         Log.i(TAG, "Starting activity: " + intent);
 
         HistoryRecord sourceRecord = null;
@@ -2784,7 +2809,7 @@
 
         HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
                 intent, resolvedType, aInfo, mConfiguration,
-                resultRecord, resultWho, requestCode);
+                resultRecord, resultWho, requestCode, componentSpecified);
         r.startTime = SystemClock.uptimeMillis();
 
         HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
@@ -3118,6 +3143,8 @@
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
 
+        final boolean componentSpecified = intent.getComponent() != null;
+        
         // Don't modify the client's object!
         intent = new Intent(intent);
 
@@ -3157,7 +3184,7 @@
             int res = startActivityLocked(caller, intent, resolvedType,
                     grantedUriPermissions, grantedMode, aInfo,
                     resultTo, resultWho, requestCode, -1, -1,
-                    onlyIfNeeded);
+                    onlyIfNeeded, componentSpecified);
             Binder.restoreCallingIdentity(origId);
             return res;
         }
@@ -3247,7 +3274,7 @@
             // those are not yet exposed to user code, so there is no need.
             int res = startActivityLocked(r.app.thread, intent,
                     r.resolvedType, null, 0, aInfo, resultTo, resultWho,
-                    requestCode, -1, r.launchedFromUid, false);
+                    requestCode, -1, r.launchedFromUid, false, false);
             Binder.restoreCallingIdentity(origId);
 
             r.finishing = wasFinishing;
@@ -3261,6 +3288,8 @@
     final int startActivityInPackage(int uid,
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, boolean onlyIfNeeded) {
+        final boolean componentSpecified = intent.getComponent() != null;
+        
         // Don't modify the client's object!
         intent = new Intent(intent);
 
@@ -3291,7 +3320,7 @@
         synchronized(this) {
             return startActivityLocked(null, intent, resolvedType,
                     null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
-                    onlyIfNeeded);
+                    onlyIfNeeded, componentSpecified);
         }
     }
 
@@ -5678,9 +5707,9 @@
 
     public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
         outInfo.availMem = Process.getFreeMemory();
-        outInfo.threshold = SECONDARY_SERVER_MEM;
+        outInfo.threshold = HOME_APP_MEM;
         outInfo.lowMemory = outInfo.availMem <
-                (SECONDARY_SERVER_MEM + ((HIDDEN_APP_MEM-SECONDARY_SERVER_MEM)/2));
+                (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
     }
     
     // =========================================================
@@ -7798,7 +7827,10 @@
                         currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
                     } else if (adj >= HIDDEN_APP_MIN_ADJ) {
                         currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-                        currApp.lru = adj - HIDDEN_APP_MIN_ADJ;
+                        currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
+                    } else if (adj >= HOME_APP_ADJ) {
+                        currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
+                        currApp.lru = 0;
                     } else if (adj >= SECONDARY_SERVER_ADJ) {
                         currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
                     } else if (adj >= VISIBLE_APP_ADJ) {
@@ -7997,6 +8029,7 @@
 
             pw.println(" ");
             pw.println("  Total persistent processes: " + numPers);
+            pw.println("  mHomeProcess: " + mHomeProcess);
             pw.println("  mConfiguration: " + mConfiguration);
             pw.println("  mStartRunning=" + mStartRunning
                     + " mSystemReady=" + mSystemReady
@@ -8680,6 +8713,10 @@
         }
         mProcessesOnHold.remove(app);
 
+        if (app == mHomeProcess) {
+            mHomeProcess = null;
+        }
+        
         if (restart) {
             // We have components that still need to be running in the
             // process, so re-launch it.
@@ -11185,9 +11222,8 @@
 
         app.isForeground = false;
 
-        // Right now there are three interesting states: it is
-        // either the foreground app, background with activities,
-        // or background without activities.
+        // Determine the importance of the process, starting with most
+        // important to least, and assign an appropriate OOM adjustment.
         int adj;
         int N;
         if (app == TOP_APP || app.instrumentationClass != null
@@ -11207,6 +11243,10 @@
         } else if (app.foregroundServices || app.forcingToForeground != null) {
             // The user is aware of this app, so make it visible.
             adj = VISIBLE_APP_ADJ;
+        } else if (app == mHomeProcess) {
+            // This process is hosting what we currently consider to be the
+            // home app, so we don't want to let it go into the background.
+            adj = HOME_APP_ADJ;
         } else if ((N=app.activities.size()) != 0) {
             // This app is in the background with paused activities.
             adj = hiddenAdj;
@@ -11222,7 +11262,7 @@
             adj = EMPTY_APP_ADJ;
         }
 
-        // By default, we use the computed adjusted.  It may be changed if
+        // By default, we use the computed adjustment.  It may be changed if
         // there are applications dependent on our services or providers, but
         // this gives us a baseline and makes sure we don't get into an
         // infinite recursion.