auto import from //depot/cupcake/@136594
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 4b45828..a254081 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -54,6 +54,7 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.provider.Settings;
@@ -619,7 +620,7 @@
         }
         if (mShowRequested) {
             if (DEBUG) Log.v(TAG, "Attach new input asks to show input");
-            showCurrentInputLocked(getAppShowFlags());
+            showCurrentInputLocked(getAppShowFlags(), null);
         }
         return needResult
                 ? new InputBindResult(session.session, mCurId, mCurSeq)
@@ -908,7 +909,8 @@
         }
     }
     
-    public void showSoftInput(IInputMethodClient client, int flags) {
+    public boolean showSoftInput(IInputMethodClient client, int flags,
+            ResultReceiver resultReceiver) {
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mMethodMap) {
@@ -920,21 +922,22 @@
                         // be made before input is started in it.
                         if (!mIWindowManager.inputMethodClientHasFocus(client)) {
                             Log.w(TAG, "Ignoring showSoftInput of: " + client);
-                            return;
+                            return false;
                         }
                     } catch (RemoteException e) {
+                        return false;
                     }
                 }
     
                 if (DEBUG) Log.v(TAG, "Client requesting input be shown");
-                showCurrentInputLocked(flags);
+                return showCurrentInputLocked(flags, resultReceiver);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
     }
     
-    void showCurrentInputLocked(int flags) {
+    boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
         mShowRequested = true;
         if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
             mShowExplicitlyRequested = true;
@@ -943,10 +946,13 @@
             mShowExplicitlyRequested = true;
             mShowForced = true;
         }
+        boolean res = false;
         if (mCurMethod != null) {
-            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIO(
-                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod));
+            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
+                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
+                    resultReceiver));
             mInputShown = true;
+            res = true;
         } else if (mHaveConnection && SystemClock.uptimeMillis()
                 < (mLastBindTime+TIME_TO_RECONNECT)) {
             // The client has asked to have the input method shown, but
@@ -958,9 +964,12 @@
             mContext.unbindService(this);
             mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE);
         }
+        
+        return res;
     }
     
-    public void hideSoftInput(IInputMethodClient client, int flags) {
+    public boolean hideSoftInput(IInputMethodClient client, int flags,
+            ResultReceiver resultReceiver) {
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mMethodMap) {
@@ -972,40 +981,46 @@
                         // be made before input is started in it.
                         if (!mIWindowManager.inputMethodClientHasFocus(client)) {
                             Log.w(TAG, "Ignoring hideSoftInput of: " + client);
-                            return;
+                            return false;
                         }
                     } catch (RemoteException e) {
+                        return false;
                     }
                 }
     
                 if (DEBUG) Log.v(TAG, "Client requesting input be hidden");
-                hideCurrentInputLocked(flags);
+                return hideCurrentInputLocked(flags, resultReceiver);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
     }
     
-    void hideCurrentInputLocked(int flags) {
+    boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
         if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
                 && (mShowExplicitlyRequested || mShowForced)) {
             if (DEBUG) Log.v(TAG,
                     "Not hiding: explicit show not cancelled by non-explicit hide");
-            return;
+            return false;
         }
         if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
             if (DEBUG) Log.v(TAG,
                     "Not hiding: forced show not cancelled by not-always hide");
-            return;
+            return false;
         }
+        boolean res;
         if (mInputShown && mCurMethod != null) {
-            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
-                    MSG_HIDE_SOFT_INPUT, mCurMethod));
+            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
+                    MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
+            res = true;
+        } else {
+            res = false;
         }
         mInputShown = false;
         mShowRequested = false;
         mShowExplicitlyRequested = false;
         mShowForced = false;
+        return res;
     }
     
     public void windowGainedFocus(IInputMethodClient client,
@@ -1045,7 +1060,7 @@
                                 // be behind any soft input window, so hide the
                                 // soft input window if it is shown.
                                 if (DEBUG) Log.v(TAG, "Unspecified window will hide input");
-                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS);
+                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
                             }
                         } else if (isTextEditor && (softInputMode &
                                 WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
@@ -1055,7 +1070,7 @@
                             // There is a focus view, and we are navigating forward
                             // into the window, so show the input window for the user.
                             if (DEBUG) Log.v(TAG, "Unspecified window will show input");
-                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
+                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
                         }
                         break;
                     case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
@@ -1065,23 +1080,23 @@
                         if ((softInputMode &
                                 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
                             if (DEBUG) Log.v(TAG, "Window asks to hide input going forward");
-                            hideCurrentInputLocked(0);
+                            hideCurrentInputLocked(0, null);
                         }
                         break;
                     case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
                         if (DEBUG) Log.v(TAG, "Window asks to hide input");
-                        hideCurrentInputLocked(0);
+                        hideCurrentInputLocked(0, null);
                         break;
                     case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
                         if ((softInputMode &
                                 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
                             if (DEBUG) Log.v(TAG, "Window asks to show input going forward");
-                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
+                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
                         }
                         break;
                     case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
                         if (DEBUG) Log.v(TAG, "Window asks to always show input");
-                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
+                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
                         break;
                 }
             }
@@ -1131,10 +1146,24 @@
                 Log.w(TAG, "Ignoring hideInputMethod of token: " + token);
                 return;
             }
-
             long ident = Binder.clearCallingIdentity();
             try {
-                hideCurrentInputLocked(flags);
+                hideCurrentInputLocked(flags, null);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+    
+    public void showMySoftInput(IBinder token, int flags) {
+        synchronized (mMethodMap) {
+            if (token == null || mCurToken != token) {
+                Log.w(TAG, "Ignoring hideInputMethod of token: " + token);
+                return;
+            }
+            long ident = Binder.clearCallingIdentity();
+            try {
+                showCurrentInputLocked(flags, null);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -1185,14 +1214,18 @@
                 }
                 return true;
             case MSG_SHOW_SOFT_INPUT:
+                args = (HandlerCaller.SomeArgs)msg.obj;
                 try {
-                    ((IInputMethod)msg.obj).showSoftInput(msg.arg1);
+                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1,
+                            (ResultReceiver)args.arg2);
                 } catch (RemoteException e) {
                 }
                 return true;
             case MSG_HIDE_SOFT_INPUT:
+                args = (HandlerCaller.SomeArgs)msg.obj;
                 try {
-                    ((IInputMethod)msg.obj).hideSoftInput();
+                    ((IInputMethod)args.arg1).hideSoftInput(0,
+                            (ResultReceiver)args.arg2);
                 } catch (RemoteException e) {
                 }
                 return true;
@@ -1212,7 +1245,6 @@
                 } catch (RemoteException e) {
                 }
                 return true;
-                
             // ---------------------------------------------------------
                 
             case MSG_START_INPUT:
@@ -1486,7 +1518,7 @@
             }
         }
     }
-    
+
     // ----------------------------------------------------------------------
     
     @Override
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 9d69114..e48e047 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -221,6 +221,9 @@
     // Wifi Manager
     private WifiManager mWifiManager;
 
+    private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
+    private boolean mWifiEnabled = false;
+
     /**
      * A wrapper class holding either an ILocationListener or a PendingIntent to receive
      * location updates.
@@ -597,16 +600,6 @@
 
         // Create a wifi lock for future use
         mWifiLock = getWifiWakelockLocked();
-
-        // There might be an existing wifi scan available
-        if (mWifiManager != null) {
-            List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
-            if (wifiScanResults != null && wifiScanResults.size() != 0) {
-                if (mNetworkLocationInterface != null) {
-                    mNetworkLocationInterface.updateWifiScanResults(wifiScanResults);
-                }
-            }
-        }
     }
 
     public void setInstallCallback(InstallCallback callback) {
@@ -625,6 +618,31 @@
             mNetworkLocationProvider = (LocationProviderImpl)provider;
             LocationProviderImpl.addProvider(mNetworkLocationProvider);
             updateProvidersLocked();
+            
+            // notify NetworkLocationProvider of any events it might have missed
+            synchronized (mLocationListeners) {
+                mNetworkLocationProvider.updateNetworkState(mNetworkState);
+                mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
+                mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);
+
+                if (mLastCellState != null) {
+                    if (mCollector != null) {
+                        mCollector.updateCellState(mLastCellState);
+                    }
+                    mNetworkLocationProvider.updateCellState(mLastCellState);
+                }
+
+                // There might be an existing wifi scan available
+                if (mWifiManager != null) {
+                    List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
+                    if (wifiScanResults != null && wifiScanResults.size() != 0) {
+                        mNetworkLocationInterface.updateWifiScanResults(wifiScanResults);
+                        if (mCollector != null) {
+                            mCollector.updateWifiScanResults(wifiScanResults);
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -1992,12 +2010,12 @@
                 }
 
             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
-                int networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
-
                 boolean noConnectivity =
                     intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
                 if (!noConnectivity) {
-                    networkState = LocationProvider.AVAILABLE;
+                    mNetworkState = LocationProvider.AVAILABLE;
+                } else {
+                    mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
                 }
 
                 // Notify location providers of current network state
@@ -2005,7 +2023,7 @@
                     List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
                     for (LocationProviderImpl provider : providers) {
                         if (provider.requiresNetwork()) {
-                            provider.updateNetworkState(networkState);
+                            provider.updateNetworkState(mNetworkState);
                         }
                     }
                 }
@@ -2014,11 +2032,10 @@
                 int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                     WifiManager.WIFI_STATE_UNKNOWN);
 
-                boolean enabled;
                 if (state == WifiManager.WIFI_STATE_ENABLED) {
-                    enabled = true;
+                    mWifiEnabled = true;
                 } else if (state == WifiManager.WIFI_STATE_DISABLED) {
-                    enabled = false;
+                    mWifiEnabled = false;
                 } else {
                     return;
                 }
@@ -2026,7 +2043,7 @@
                 // Notify network provider of current wifi enabled state
                 synchronized (mLocationListeners) {
                     if (mNetworkLocationInterface != null) {
-                        mNetworkLocationInterface.updateWifiEnabledState(enabled);
+                        mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
                     }
                 }
 
diff --git a/services/java/com/android/server/SensorService.java b/services/java/com/android/server/SensorService.java
index 29b45ab..b2530383f 100644
--- a/services/java/com/android/server/SensorService.java
+++ b/services/java/com/android/server/SensorService.java
@@ -45,7 +45,7 @@
     private static final int SENSOR_DISABLE = -1;
     
     /**
-     * Battery statistics to be updated when sensors are enabled and diabled.
+     * Battery statistics to be updated when sensors are enabled and disabled.
      */
     final IBatteryStats mBatteryStats = BatteryStatsService.getService();
 
@@ -119,7 +119,10 @@
         }
         Binder.restoreCallingIdentity(identity);
 
-        if (binder == null) throw new NullPointerException("listener is null in enableSensor");
+        if (binder == null) {
+            Log.w(TAG, "listener is null (sensor=" + name + ", id=" + sensor + ")");
+            return false;
+        }
 
         synchronized(mListeners) {
             if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) {
@@ -145,7 +148,11 @@
             }
             
             if (l == null) {
-                throw new NullPointerException("no Listener object in enableSensor");
+                // by construction, this means we're disabling a listener we
+                // don't know about...
+                Log.w(TAG, "listener with binder " + binder + 
+                        ", doesn't exist (sensor=" + name + ", id=" + sensor + ")");
+                return false;
             }
             
             if (minDelay >= 0) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 21e5ee1..cb16c98 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -2076,6 +2076,7 @@
             int curGroup = 0;
             int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
             boolean haveGroup = false;
+            boolean lastFullscreen = false;
             while (pos >= 0) {
                 AppWindowToken wtoken = mAppTokens.get(pos);
                 pos--;
@@ -2090,16 +2091,19 @@
                 } else if (curGroup != wtoken.groupId) {
                     // If we have hit a new application group, and the bottom
                     // of the previous group didn't explicitly say to use
-                    // the orientation behind it, then we'll stick with the
+                    // the orientation behind it, and the last app was
+                    // full screen, then we'll stick with the
                     // user's orientation.
-                    if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+                    if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
+                            && lastFullscreen) {
                         return lastOrientation;
                     }
                 }
                 int or = wtoken.requestedOrientation;
                 // If this application is fullscreen, then just take whatever
                 // orientation it has and ignores whatever is under it.
-                if (wtoken.appFullscreen) {
+                lastFullscreen = wtoken.appFullscreen;
+                if (lastFullscreen) {
                     return or;
                 }
                 // If this application has requested an explicit orientation,
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.
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index b407208..0f62471 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -55,6 +55,8 @@
     final String taskAffinity; // as per ActivityInfo.taskAffinity
     final boolean stateNotNeeded; // As per ActivityInfo.flags
     final boolean fullscreen;     // covers the full screen?
+    final boolean componentSpecified;  // did caller specifiy an explicit component?
+    final boolean isHomeActivity; // do we consider this to be a home activity?
     final String baseDir;   // where activity source (resources etc) located
     final String resDir;   // where public activity source (public resources etc) located
     final String dataDir;   // where activity data should go
@@ -102,8 +104,8 @@
         pw.println(prefix + this);
         pw.println(prefix + "packageName=" + packageName
               + " processName=" + processName);
-        pw.println(prefix + "app=" + app);
-        pw.println(prefix + "launchedFromUid=" + launchedFromUid);
+        pw.println(prefix + "launchedFromUid=" + launchedFromUid
+                + " app=" + app);
         pw.println(prefix + intent);
         pw.println(prefix + "frontOfTask=" + frontOfTask + " task=" + task);
         pw.println(prefix + "taskAffinity=" + taskAffinity);
@@ -112,6 +114,9 @@
         pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
                 + " icon=0x" + Integer.toHexString(icon)
                 + " theme=0x" + Integer.toHexString(theme));
+        pw.println(prefix + "stateNotNeeded=" + stateNotNeeded
+                + " componentSpecified=" + componentSpecified
+                + " isHomeActivity=" + isHomeActivity);
         pw.println(prefix + "configuration=" + configuration);
         pw.println(prefix + "resultTo=" + resultTo
               + " resultWho=" + resultWho + " resultCode=" + requestCode);
@@ -140,13 +145,15 @@
     HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
             int _launchedFromUid, Intent _intent, String _resolvedType,
             ActivityInfo aInfo, Configuration _configuration,
-            HistoryRecord _resultTo, String _resultWho, int _reqCode) {
+            HistoryRecord _resultTo, String _resultWho, int _reqCode,
+            boolean _componentSpecified) {
         service = _service;
         info = aInfo;
         launchedFromUid = _launchedFromUid;
         intent = _intent;
         shortComponentName = _intent.getComponent().flattenToShortString();
         resolvedType = _resolvedType;
+        componentSpecified = _componentSpecified;
         configuration = _configuration;
         resultTo = _resultTo;
         resultWho = _resultWho;
@@ -216,6 +223,29 @@
                     && !ent.array.getBoolean(
                     com.android.internal.R.styleable.Window_windowIsTranslucent, false);
             
+            if (!_componentSpecified || _launchedFromUid == Process.myUid()
+                    || _launchedFromUid == 0) {
+                // If we know the system has determined the component, then
+                // we can consider this to be a home activity...
+                if (Intent.ACTION_MAIN.equals(_intent.getAction()) &&
+                        _intent.hasCategory(Intent.CATEGORY_HOME) &&
+                        _intent.getCategories().size() == 1 &&
+                        _intent.getData() == null &&
+                        _intent.getType() == null &&
+                        (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
+                        !"android".equals(realActivity.getClassName())) {
+                    // This sure looks like a home activity!
+                    // Note the last check is so we don't count the resolver
+                    // activity as being home...  really, we don't care about
+                    // doing anything special with something that comes from
+                    // the core framework package.
+                    isHomeActivity = true;
+                } else {
+                    isHomeActivity = false;
+                }
+            } else {
+                isHomeActivity = false;
+            }
         } else {
             realActivity = null;
             taskAffinity = null;
@@ -226,6 +256,7 @@
             processName = null;
             packageName = null;
             fullscreen = true;
+            isHomeActivity = false;
         }
     }