Merge "InputFilter not updated on global accessibility change."
diff --git a/api/current.txt b/api/current.txt
index 91cf3fa..77e31b9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2331,7 +2331,7 @@
     method public abstract void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
   }
 
-  public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+  public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
     ctor public Activity();
     method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public void closeContextMenu();
@@ -2436,6 +2436,7 @@
     method protected void onTitleChanged(java.lang.CharSequence, int);
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
+    method public void onTrimMemory(int);
     method public void onUserInteraction();
     method protected void onUserLeaveHint();
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -2731,12 +2732,25 @@
     ctor public AliasActivity();
   }
 
-  public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks {
+  public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
     ctor public Application();
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public void onCreate();
     method public void onLowMemory();
     method public void onTerminate();
+    method public void onTrimMemory(int);
+    method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+    method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+  }
+
+  public static abstract interface Application.ActivityLifecycleCallbacks {
+    method public abstract void onActivityCreated(android.app.Activity, android.os.Bundle);
+    method public abstract void onActivityDestroyed(android.app.Activity);
+    method public abstract void onActivityPaused(android.app.Activity);
+    method public abstract void onActivityResumed(android.app.Activity);
+    method public abstract void onActivitySaveInstanceState(android.app.Activity, android.os.Bundle);
+    method public abstract void onActivityStarted(android.app.Activity);
+    method public abstract void onActivityStopped(android.app.Activity);
   }
 
   public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
@@ -2955,7 +2969,7 @@
     method public void setSelectedGroup(int);
   }
 
-  public class Fragment implements android.content.ComponentCallbacks android.view.View.OnCreateContextMenuListener {
+  public class Fragment implements android.content.ComponentCallbacks2 android.view.View.OnCreateContextMenuListener {
     ctor public Fragment();
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public final boolean equals(java.lang.Object);
@@ -3009,6 +3023,7 @@
     method public void onSaveInstanceState(android.os.Bundle);
     method public void onStart();
     method public void onStop();
+    method public void onTrimMemory(int);
     method public void onViewCreated(android.view.View, android.os.Bundle);
     method public void registerForContextMenu(android.view.View);
     method public void setArguments(android.os.Bundle);
@@ -3545,7 +3560,7 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public abstract class Service extends android.content.ContextWrapper implements android.content.ComponentCallbacks {
+  public abstract class Service extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
     ctor public Service();
     method protected void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public final android.app.Application getApplication();
@@ -3558,6 +3573,7 @@
     method public deprecated void onStart(android.content.Intent, int);
     method public int onStartCommand(android.content.Intent, int, int);
     method public void onTaskRemoved(android.content.Intent);
+    method public void onTrimMemory(int);
     method public boolean onUnbind(android.content.Intent);
     method public final void startForeground(int, android.app.Notification);
     method public final void stopForeground(boolean);
@@ -4442,6 +4458,14 @@
     method public abstract void onLowMemory();
   }
 
+  public abstract interface ComponentCallbacks2 implements android.content.ComponentCallbacks {
+    method public abstract void onTrimMemory(int);
+    field public static final int TRIM_MEMORY_BACKGROUND = 40; // 0x28
+    field public static final int TRIM_MEMORY_COMPLETE = 80; // 0x50
+    field public static final int TRIM_MEMORY_MODERATE = 60; // 0x3c
+    field public static final int TRIM_MEMORY_UI_HIDDEN = 20; // 0x14
+  }
+
   public final class ComponentName implements java.lang.Cloneable java.lang.Comparable android.os.Parcelable {
     ctor public ComponentName(java.lang.String, java.lang.String);
     ctor public ComponentName(android.content.Context, java.lang.String);
@@ -4463,7 +4487,7 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public abstract class ContentProvider implements android.content.ComponentCallbacks {
+  public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
     ctor public ContentProvider();
     method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
     method public void attachInfo(android.content.Context, android.content.pm.ProviderInfo);
@@ -4481,6 +4505,7 @@
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public abstract boolean onCreate();
     method public void onLowMemory();
+    method public void onTrimMemory(int);
     method public android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method protected final android.os.ParcelFileDescriptor openFileHelper(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -4734,6 +4759,7 @@
     method public abstract android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
     method public abstract android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
     method public abstract deprecated android.graphics.drawable.Drawable peekWallpaper();
+    method public void registerComponentCallbacks(android.content.ComponentCallbacks);
     method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
     method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
     method public abstract void removeStickyBroadcast(android.content.Intent);
@@ -4754,15 +4780,21 @@
     method public abstract android.content.ComponentName startService(android.content.Intent);
     method public abstract boolean stopService(android.content.Intent);
     method public abstract void unbindService(android.content.ServiceConnection);
+    method public void unregisterComponentCallbacks(android.content.ComponentCallbacks);
     method public abstract void unregisterReceiver(android.content.BroadcastReceiver);
     field public static final java.lang.String ACCESSIBILITY_SERVICE = "accessibility";
     field public static final java.lang.String ACCOUNT_SERVICE = "account";
     field public static final java.lang.String ACTIVITY_SERVICE = "activity";
     field public static final java.lang.String ALARM_SERVICE = "alarm";
     field public static final java.lang.String AUDIO_SERVICE = "audio";
+    field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
+    field public static final int BIND_ADJUST_WITH_ACTIVITY = 64; // 0x40
+    field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10
     field public static final int BIND_AUTO_CREATE = 1; // 0x1
     field public static final int BIND_DEBUG_UNBIND = 2; // 0x2
+    field public static final int BIND_IMPORTANT = 64; // 0x40
     field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
+    field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -22666,8 +22698,11 @@
     field protected static final int[] SELECTED_STATE_SET;
     field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
     field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
-    field public static final int STATUS_BAR_HIDDEN = 1; // 0x1
-    field public static final int STATUS_BAR_VISIBLE = 0; // 0x0
+    field public static final deprecated int STATUS_BAR_HIDDEN = 1; // 0x1
+    field public static final deprecated int STATUS_BAR_VISIBLE = 0; // 0x0
+    field public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2; // 0x2
+    field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
+    field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
     field public static android.util.Property TRANSLATION_X;
     field public static android.util.Property TRANSLATION_Y;
     field protected static final java.lang.String VIEW_LOG_TAG = "View";
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index fb1570e..d5b669e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -19,7 +19,7 @@
 import com.android.internal.app.ActionBarImpl;
 import com.android.internal.policy.PolicyManager;
 
-import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -626,7 +626,7 @@
 public class Activity extends ContextThemeWrapper
         implements LayoutInflater.Factory2,
         Window.Callback, KeyEvent.Callback,
-        OnCreateContextMenuListener, ComponentCallbacks {
+        OnCreateContextMenuListener, ComponentCallbacks2 {
     private static final String TAG = "Activity";
 
     /** Standard activity result: operation canceled. */
@@ -859,6 +859,7 @@
                     ? mLastNonConfigurationInstances.fragments : null);
         }
         mFragments.dispatchCreate();
+        getApplication().dispatchActivityCreated(this, savedInstanceState);
         mCalled = true;
     }
 
@@ -1001,6 +1002,8 @@
             }
             mCheckedForLoaderManager = true;
         }
+
+        getApplication().dispatchActivityStarted(this);
     }
 
     /**
@@ -1048,6 +1051,7 @@
      * @see #onPause
      */
     protected void onResume() {
+        getApplication().dispatchActivityResumed(this);
         mCalled = true;
     }
 
@@ -1158,6 +1162,7 @@
         if (p != null) {
             outState.putParcelable(FRAGMENTS_TAG, p);
         }
+        getApplication().dispatchActivitySaveInstanceState(this, outState);
     }
 
     /**
@@ -1234,6 +1239,7 @@
      * @see #onStop
      */
     protected void onPause() {
+        getApplication().dispatchActivityPaused(this);
         mCalled = true;
     }
 
@@ -1320,6 +1326,7 @@
      */
     protected void onStop() {
         if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
+        getApplication().dispatchActivityStopped(this);
         mCalled = true;
     }
 
@@ -1382,6 +1389,8 @@
         if (mSearchManager != null) {
             mSearchManager.stopSearch();
         }
+
+        getApplication().dispatchActivityDestroyed(this);
     }
 
     /**
@@ -1580,12 +1589,17 @@
         nci.loaders = mAllLoaderManagers;
         return nci;
     }
-    
+
     public void onLowMemory() {
         mCalled = true;
         mFragments.dispatchLowMemory();
     }
-    
+
+    public void onTrimMemory(int level) {
+        mCalled = true;
+        mFragments.dispatchTrimMemory(level);
+    }
+
     /**
      * Return the FragmentManager for interacting with fragments associated
      * with this activity.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1e93f88..8931675 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -18,7 +18,7 @@
 
 import android.app.backup.BackupAgent;
 import android.content.BroadcastReceiver;
-import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.Context;
@@ -3258,10 +3258,10 @@
         }
     }
 
-    ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
+    ArrayList<ComponentCallbacks2> collectComponentCallbacksLocked(
             boolean allActivities, Configuration newConfig) {
-        ArrayList<ComponentCallbacks> callbacks
-                = new ArrayList<ComponentCallbacks>();
+        ArrayList<ComponentCallbacks2> callbacks
+                = new ArrayList<ComponentCallbacks2>();
 
         if (mActivities.size() > 0) {
             Iterator<ActivityClientRecord> it = mActivities.values().iterator();
@@ -3311,10 +3311,10 @@
         return callbacks;
     }
 
-    private void performConfigurationChanged(
-            ComponentCallbacks cb, Configuration config) {
+    private final void performConfigurationChanged(
+            ComponentCallbacks2 cb, Configuration config) {
         // Only for Activity objects, check that they actually call up to their
-        // superclass implementation.  ComponentCallbacks is an interface, so
+        // superclass implementation.  ComponentCallbacks2 is an interface, so
         // we check the runtime type and act accordingly.
         Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
         if (activity != null) {
@@ -3418,7 +3418,7 @@
     
     final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
 
-        ArrayList<ComponentCallbacks> callbacks = null;
+        ArrayList<ComponentCallbacks2> callbacks = null;
 
         synchronized (mPackages) {
             if (mPendingConfiguration != null) {
@@ -3558,7 +3558,7 @@
     }
         
     final void handleLowMemory() {
-        ArrayList<ComponentCallbacks> callbacks;
+        ArrayList<ComponentCallbacks2> callbacks;
 
         synchronized (mPackages) {
             callbacks = collectComponentCallbacksLocked(true, null);
@@ -3583,6 +3583,16 @@
 
     final void handleTrimMemory(int level) {
         WindowManagerImpl.getDefault().trimMemory(level);
+        ArrayList<ComponentCallbacks2> callbacks;
+
+        synchronized (mPackages) {
+            callbacks = collectComponentCallbacksLocked(true, null);
+        }
+
+        final int N = callbacks.size();
+        for (int i=0; i<N; i++) {
+            callbacks.get(i).onTrimMemory(level);
+        }
     }
 
     private void handleBindApplication(AppBindData data) {
@@ -4128,7 +4138,7 @@
             }
         }
         
-        ViewRootImpl.addConfigCallback(new ComponentCallbacks() {
+        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
             public void onConfigurationChanged(Configuration newConfig) {
                 synchronized (mPackages) {
                     // We need to apply this change to the resources
@@ -4148,6 +4158,8 @@
             }
             public void onLowMemory() {
             }
+            public void onTrimMemory(int level) {
+            }
         });
     }
 
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 10cc9f8..dd9ea26 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -16,10 +16,14 @@
 
 package android.app;
 
+import java.util.ArrayList;
+
 import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.res.Configuration;
+import android.os.Bundle;
 
 /**
  * Base class for those who need to maintain global application state. You can
@@ -36,10 +40,25 @@
  * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
  * when first constructing the singleton.</p>
  */
-public class Application extends ContextWrapper implements ComponentCallbacks {
+public class Application extends ContextWrapper implements ComponentCallbacks2 {
+    private ArrayList<ComponentCallbacks> mComponentCallbacks =
+            new ArrayList<ComponentCallbacks>();
+    private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
+            new ArrayList<ActivityLifecycleCallbacks>();
+
     /** @hide */
     public LoadedApk mLoadedApk;
-    
+
+    public interface ActivityLifecycleCallbacks {
+        void onActivityCreated(Activity activity, Bundle savedInstanceState);
+        void onActivityStarted(Activity activity);
+        void onActivityResumed(Activity activity);
+        void onActivityPaused(Activity activity);
+        void onActivityStopped(Activity activity);
+        void onActivitySaveInstanceState(Activity activity, Bundle outState);
+        void onActivityDestroyed(Activity activity);
+    }
+
     public Application() {
         super(null);
     }
@@ -63,11 +82,59 @@
      */
     public void onTerminate() {
     }
-    
+
     public void onConfigurationChanged(Configuration newConfig) {
+        Object[] callbacks = collectComponentCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
+            }
+        }
     }
-    
+
     public void onLowMemory() {
+        Object[] callbacks = collectComponentCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ComponentCallbacks)callbacks[i]).onLowMemory();
+            }
+        }
+    }
+
+    public void onTrimMemory(int level) {
+        Object[] callbacks = collectComponentCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                Object c = callbacks[i];
+                if (c instanceof ComponentCallbacks2) {
+                    ((ComponentCallbacks2)c).onTrimMemory(level);
+                }
+            }
+        }
+    }
+
+    public void registerComponentCallbacks(ComponentCallbacks callback) {
+        synchronized (mComponentCallbacks) {
+            mComponentCallbacks.add(callback);
+        }
+    }
+
+    public void unregisterComponentCallbacks(ComponentCallbacks callback) {
+        synchronized (mComponentCallbacks) {
+            mComponentCallbacks.remove(callback);
+        }
+    }
+
+    public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
+        synchronized (mActivityLifecycleCallbacks) {
+            mActivityLifecycleCallbacks.add(callback);
+        }
+    }
+
+    public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
+        synchronized (mActivityLifecycleCallbacks) {
+            mActivityLifecycleCallbacks.remove(callback);
+        }
     }
     
     // ------------------ Internal API ------------------
@@ -79,4 +146,89 @@
         attachBaseContext(context);
         mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
     }
+
+    /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
+                        savedInstanceState);
+            }
+        }
+    }
+
+    /* package */ void dispatchActivityStarted(Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity);
+            }
+        }
+    }
+
+    /* package */ void dispatchActivityResumed(Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity);
+            }
+        }
+    }
+
+    /* package */ void dispatchActivityPaused(Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);
+            }
+        }
+    }
+
+    /* package */ void dispatchActivityStopped(Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity);
+            }
+        }
+    }
+
+    /* package */ void dispatchActivitySaveInstanceState(Activity activity, Bundle outState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity,
+                        outState);
+            }
+        }
+    }
+
+    /* package */ void dispatchActivityDestroyed(Activity activity) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
+            }
+        }
+    }
+
+    private Object[] collectComponentCallbacks() {
+        Object[] callbacks = null;
+        synchronized (mComponentCallbacks) {
+            if (mComponentCallbacks.size() > 0) {
+                callbacks = mComponentCallbacks.toArray();
+            }
+        }
+        return callbacks;
+    }
+
+    private Object[] collectActivityLifecycleCallbacks() {
+        Object[] callbacks = null;
+        synchronized (mActivityLifecycleCallbacks) {
+            if (mActivityLifecycleCallbacks.size() > 0) {
+                callbacks = mActivityLifecycleCallbacks.toArray();
+            }
+        }
+        return callbacks;
+    }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index a99cec2..b4bdb2f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1109,6 +1109,12 @@
             throw new RuntimeException("Not supported in system context");
         }
         try {
+            IBinder token = getActivityToken();
+            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
+                    && mPackageInfo.getApplicationInfo().targetSdkVersion
+                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+                flags |= BIND_WAIVE_PRIORITY;
+            }
             int res = ActivityManagerNative.getDefault().bindService(
                 mMainThread.getApplicationThread(), getActivityToken(),
                 service, service.resolveTypeIfNeeded(getContentResolver()),
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index e2746d4..371e7ad 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -17,7 +17,7 @@
 package android.app;
 
 import android.animation.Animator;
-import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -332,7 +332,7 @@
  * pressing back will pop it to return the user to whatever previous state
  * the activity UI was in.
  */
-public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener {
+public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener {
     private static final HashMap<String, Class<?>> sClassMap =
             new HashMap<String, Class<?>>();
     
@@ -1182,6 +1182,10 @@
         mCalled = true;
     }
     
+    public void onTrimMemory(int level) {
+        mCalled = true;
+    }
+
     /**
      * Called when the view previously created by {@link #onCreateView} has
      * been detached from the fragment.  The next time the fragment needs
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 24550c5..c33ab2c 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1722,6 +1722,17 @@
         }
     }
 
+    public void dispatchTrimMemory(int level) {
+        if (mActive != null) {
+            for (int i=0; i<mAdded.size(); i++) {
+                Fragment f = mAdded.get(i);
+                if (f != null) {
+                    f.onTrimMemory(level);
+                }
+            }
+        }
+    }
+
     public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         boolean show = false;
         ArrayList<Fragment> newMenus = null;
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 4c21d04..ebde6e0 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -16,7 +16,7 @@
 
 package android.app;
 
-import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.ContextWrapper;
@@ -274,7 +274,7 @@
  * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.java
  *      bind}
  */
-public abstract class Service extends ContextWrapper implements ComponentCallbacks {
+public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
     private static final String TAG = "Service";
 
     public Service() {
@@ -451,7 +451,10 @@
     
     public void onLowMemory() {
     }
-    
+
+    public void onTrimMemory(int level) {
+    }
+
     /**
      * Return the communication channel to the service.  May return null if 
      * clients can not bind to the service.  The returned
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index d645ac3..c154296 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -185,7 +185,8 @@
      *
      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
      */
-    void acknowledgeFullBackupOrRestore(int token, boolean allow, in String password,
+    void acknowledgeFullBackupOrRestore(int token, boolean allow,
+            in String curPassword, in String encryptionPassword,
             IFullBackupRestoreObserver observer);
 
     /**
diff --git a/core/java/android/content/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java
index 37cc141..dad60b0 100644
--- a/core/java/android/content/ComponentCallbacks.java
+++ b/core/java/android/content/ComponentCallbacks.java
@@ -51,13 +51,4 @@
      * The system will perform a gc for you after returning from this method.
      */
     void onLowMemory();
-
-    /** @hide */
-    static final int TRIM_MEMORY_COMPLETE = 80;
-
-    /** @hide */
-    static final int TRIM_MEMORY_MODERATE = 50;
-
-    /** @hide */
-    static final int TRIM_MEMORY_BACKGROUND = 20;
 }
diff --git a/core/java/android/content/ComponentCallbacks2.java b/core/java/android/content/ComponentCallbacks2.java
new file mode 100644
index 0000000..8b9f97c
--- /dev/null
+++ b/core/java/android/content/ComponentCallbacks2.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2006 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 android.content;
+
+/**
+ * Extended {@link ComponentCallbacks} interface with a new callback for
+ * finer-grained memory management.
+ */
+public interface ComponentCallbacks2 extends ComponentCallbacks {
+
+    /**
+     * Level for {@link #onTrimMemory(int)}: the process is nearing the end
+     * of the background LRU list, and if more memory isn't found soon it will
+     * be killed.
+     */
+    static final int TRIM_MEMORY_COMPLETE = 80;
+    
+    /**
+     * Level for {@link #onTrimMemory(int)}: the process is around the middle
+     * of the background LRU list; freeing memory can help the system keep
+     * other processes running later in the list for better overall performance.
+     */
+    static final int TRIM_MEMORY_MODERATE = 60;
+    
+    /**
+     * Level for {@link #onTrimMemory(int)}: the process has gone on to the
+     * LRU list.  This is a good opportunity to clean up resources that can
+     * efficiently and quickly be re-built if the user returns to the app.
+     */
+    static final int TRIM_MEMORY_BACKGROUND = 40;
+    
+    /**
+     * Level for {@link #onTrimMemory(int)}: the process had been showing
+     * a user interface, and is no longer doing so.  Large allocations with
+     * the UI should be released at this point to allow memory to be better
+     * managed.
+     */
+    static final int TRIM_MEMORY_UI_HIDDEN = 20;
+
+    /**
+     * Called when the operating system has determined that it is a good
+     * time for a process to trim unneeded memory from its process.  This will
+     * happen for example when it goes in the background and there is not enough
+     * memory to keep as many background processes running as desired.
+     * 
+     * @param level The context of the trim, giving a hint of the amount of
+     * trimming the application may like to perform.  May be
+     * {@link #TRIM_MEMORY_COMPLETE}, {@link #TRIM_MEMORY_MODERATE},
+     * {@link #TRIM_MEMORY_BACKGROUND}, or {@link #TRIM_MEMORY_UI_HIDDEN}.
+     */
+    void onTrimMemory(int level);
+}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 1a5c675..8057d4b 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -78,7 +78,7 @@
  * ContentProvider instance, so subclasses don't have to worry about the details of
  * cross-process calls.</p>
  */
-public abstract class ContentProvider implements ComponentCallbacks {
+public abstract class ContentProvider implements ComponentCallbacks2 {
     private static final String TAG = "ContentProvider";
 
     /*
@@ -491,6 +491,9 @@
     public void onLowMemory() {
     }
 
+    public void onTrimMemory(int level) {
+    }
+
     /**
      * Implement this to handle query requests from clients.
      * This method can be called from multiple threads, as described in
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2a02446..46712a9 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -107,12 +107,17 @@
      * this still provides you with access to the service object while the
      * service is created.
      *
-     * <p>Specifying this flag also tells the system to treat the service
-     * as being as important as your own process -- that is, when deciding
-     * which process should be killed to free memory, the service will only
-     * be considered a candidate as long as the processes of any such bindings
-     * is also a candidate to be killed.  This is to avoid situations where
-     * the service is being continually created and killed due to low memory.
+     * <p>Note that prior to {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH},
+     * not supplying this flag would also impact how important the system
+     * consider's the target service's process to be.  When set, the only way
+     * for it to be raised was by binding from a service in which case it will
+     * only be important when that activity is in the foreground.  Now to
+     * achieve this behavior you must explicitly supply the new flag
+     * {@link #BIND_ADJUST_WITH_ACTIVITY}.  For compatibility, old applications
+     * that don't specify {@link #BIND_AUTO_CREATE} will automatically have
+     * the flags {@link #BIND_WAIVE_PRIORITY} and
+     * {@link #BIND_ADJUST_WITH_ACTIVITY} set for them in order to achieve
+     * the same result.
      */
     public static final int BIND_AUTO_CREATE = 0x0001;
 
@@ -139,14 +144,48 @@
     public static final int BIND_NOT_FOREGROUND = 0x0004;
 
     /**
+     * Flag for {@link #bindService}: indicates that the client application
+     * binding to this service considers the service to be more important than
+     * the app itself.  When set, the platform will try to have the out of
+     * memory kill the app before it kills the service it is bound to, though
+     * this is not guaranteed to be the case.
+     */
+    public static final int BIND_ABOVE_CLIENT = 0x0008;
+
+    /**
      * Flag for {@link #bindService}: allow the process hosting the bound
      * service to go through its normal memory management.  It will be
      * treated more like a running service, allowing the system to
      * (temporarily) expunge the process if low on memory or for some other
-     * whim it may have.
-     * @hide
+     * whim it may have, and being more aggressive about making it a candidate
+     * to be killed (and restarted) if running for a long time.
      */
-    public static final int BIND_ALLOW_OOM_MANAGEMENT = 0x0008;
+    public static final int BIND_ALLOW_OOM_MANAGEMENT = 0x0010;
+
+    /**
+     * Flag for {@link #bindService}: don't impact the scheduling or
+     * memory management priority of the target service's hosting process.
+     * Allows the service's process to be managed on the background LRU list
+     * just like a regular application process in the background.
+     */
+    public static final int BIND_WAIVE_PRIORITY = 0x0020;
+
+    /**
+     * Flag for {@link #bindService}: this service is very important to
+     * the client, so should be brought to the foreground process level
+     * when the client is.  Normally a process can only be raised to the
+     * visibility level by a client, even if that client is in the foreground.
+     */
+    public static final int BIND_IMPORTANT = 0x0040;
+
+    /**
+     * Flag for {@link #bindService}: If binding from an activity, allow the
+     * target service's process importance to be raised based on whether the
+     * activity is visible to the user, regardless whether another flag is
+     * used to reduce the amount that the client process's overall importance
+     * is used to impact it.
+     */
+    public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0040;
 
     /** Return an AssetManager instance for your application's package. */
     public abstract AssetManager getAssets();
@@ -195,6 +234,25 @@
     public abstract Context getApplicationContext();
 
     /**
+     * Add a new {@link ComponentCallbacks} to the base application of the
+     * Context, which will be called at the same times as the ComponentCallbacks
+     * methods of activities and other components are called.  Note that you
+     * <em>must</em> be sure to use {@link #unregisterComponentCallbacks} when
+     * appropriate in the future; this will not be removed for you.
+     */
+    public void registerComponentCallbacks(ComponentCallbacks callback) {
+        getApplicationContext().registerComponentCallbacks(callback);
+    }
+
+    /**
+     * Remove a {@link ComponentCallbacks} objec that was previously registered
+     * with {@link #registerComponentCallbacks(ComponentCallbacks)}.
+     */
+    public void unregisterComponentCallbacks(ComponentCallbacks callback) {
+        getApplicationContext().unregisterComponentCallbacks(callback);
+    }
+
+    /**
      * Return a localized, styled CharSequence from the application's package's
      * default string table.
      *
@@ -1219,8 +1277,10 @@
      *      {@link IntentFilter} published by a service.
      * @param conn Receives information as the service is started and stopped.
      * @param flags Operation options for the binding.  May be 0,
-     *          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND}, or
-     *          {@link #BIND_NOT_FOREGROUND}.
+     *          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
+     *          {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
+     *          {@link #BIND_ALLOW_OOM_MANAGEMENT}, or
+     *          {@link #BIND_WAIVE_PRIORITY}.
      * @return If you have successfully bound to the service, true is returned;
      *         false is returned if the connection is not made so you will not
      *         receive the service object.
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 132f3ba..75646fd 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -80,9 +80,9 @@
     public LinkProperties(LinkProperties source) {
         if (source != null) {
             mIfaceName = source.getInterfaceName();
-            mLinkAddresses = source.getLinkAddresses();
-            mDnses = source.getDnses();
-            mRoutes = source.getRoutes();
+            for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l);
+            for (InetAddress i : source.getDnses()) mDnses.add(i);
+            for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
             mHttpProxy = (source.getHttpProxy() == null)  ?
                 null : new ProxyProperties(source.getHttpProxy());
         }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 4e4923b..4e20358 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -17,7 +17,7 @@
 
 package android.view;
 
-import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacks2;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
@@ -975,10 +975,10 @@
             }
 
             switch (level) {
-                case ComponentCallbacks.TRIM_MEMORY_MODERATE:
+                case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                     GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
                     break;
-                case ComponentCallbacks.TRIM_MEMORY_COMPLETE:
+                case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                     GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
                     break;
             }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 580d450..dd7eaa9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1784,18 +1784,51 @@
     public static final int OVER_SCROLL_NEVER = 2;
 
     /**
-     * View has requested the status bar to be visible (the default).
+     * View has requested the system UI (status bar) to be visible (the default).
      *
      * @see #setSystemUiVisibility(int)
      */
-    public static final int STATUS_BAR_VISIBLE = 0;
+    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
 
     /**
-     * View has requested the status bar to be hidden.
+     * View has requested the system UI to enter an unobtrusive "low profile" mode.
+     *
+     * This is for use in games, book readers, video players, or any other "immersive" application
+     * where the usual system chrome is deemed too distracting. 
+     *
+     * In low profile mode, the status bar and/or navigation icons may dim.
      *
      * @see #setSystemUiVisibility(int)
      */
-    public static final int STATUS_BAR_HIDDEN = 0x00000001;
+    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
+
+    /**
+     * View has requested that the system navigation be temporarily hidden.
+     *
+     * This is an even less obtrusive state than that called for by
+     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
+     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
+     * those to disappear. This is useful (in conjunction with the
+     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 
+     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
+     * window flags) for displaying content using every last pixel on the display.
+     *
+     * There is a limitation: because navigation controls are so important, the least user
+     * interaction will cause them to reappear immediately.
+     *
+     * @see #setSystemUiVisibility(int)
+     */
+    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
+
+    /**
+     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
+     */
+    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
+
+    /**
+     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
+     */
+    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
 
     /**
      * @hide
@@ -1889,7 +1922,7 @@
     /**
      * @hide
      */
-    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = STATUS_BAR_HIDDEN;
+    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
 
     /**
      * Controls the over-scroll mode for this view.
@@ -1934,7 +1967,17 @@
      * This view's request for the visibility of the status bar.
      * @hide
      */
-    @ViewDebug.ExportedProperty()
+    @ViewDebug.ExportedProperty(flagMapping = {
+        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
+                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
+                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
+        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
+        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
+                                equals = SYSTEM_UI_FLAG_VISIBLE,
+                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
+    })
     int mSystemUiVisibility;
 
     /**
@@ -12538,7 +12581,8 @@
 
     /**
      * Request that the visibility of the status bar be changed.
-     * @param visibility  Either {@link #STATUS_BAR_VISIBLE} or {@link #STATUS_BAR_HIDDEN}.
+     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
+     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
      */
     public void setSystemUiVisibility(int visibility) {
         if (visibility != mSystemUiVisibility) {
@@ -12551,7 +12595,8 @@
 
     /**
      * Returns the status bar visibility that this view has requested.
-     * @return Either {@link #STATUS_BAR_VISIBLE} or {@link #STATUS_BAR_HIDDEN}.
+     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
+     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
      */
     public int getSystemUiVisibility() {
         return mSystemUiVisibility;
@@ -13654,7 +13699,8 @@
          * Called when the status bar changes visibility because of a call to
          * {@link View#setSystemUiVisibility(int)}.
          *
-         * @param visibility {@link #STATUS_BAR_VISIBLE} or {@link #STATUS_BAR_HIDDEN}.
+         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
+         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
          */
         public void onSystemUiVisibilityChange(int visibility);
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0bd5a2a..b22ab7e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -21,6 +21,7 @@
 import android.app.ActivityManagerNative;
 import android.content.ClipDescription;
 import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
@@ -554,7 +555,7 @@
         if (mThread != Thread.currentThread()) {
             if (mAttachInfo.mHardwareRenderer != null &&
                     mAttachInfo.mHardwareRenderer.isEnabled()) {
-                HardwareRenderer.trimMemory(ComponentCallbacks.TRIM_MEMORY_MODERATE);
+                HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE);
             }
         } else {
             if (mAttachInfo.mHardwareRenderer != null &&
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c11fc10..3916e86 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -30,7 +30,7 @@
     void disable(int state);
     void animateExpand();
     void animateCollapse();
-    void setLightsOn(boolean on);
+    void setSystemUiVisibility(int vis);
     void topAppWindowChanged(boolean menuVisible);
     void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
     void setHardKeyboardStatus(boolean available, boolean enabled);
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index 2a045e3..eae1ac8 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -32,5 +32,6 @@
             in ITextServicesSessionListener tsListener,
             in ISpellCheckerSessionListener scListener);
     oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
+    oneway void setCurrentSpellChecker(in SpellCheckerInfo info);
     SpellCheckerInfo[] getEnabledSpellCheckers();
 }
diff --git a/core/jni/android/graphics/NinePatchImpl.cpp b/core/jni/android/graphics/NinePatchImpl.cpp
index a3e36ee..579749a 100644
--- a/core/jni/android/graphics/NinePatchImpl.cpp
+++ b/core/jni/android/graphics/NinePatchImpl.cpp
@@ -160,6 +160,14 @@
         return;
     }
     
+    // if the nine patch is bigger than the dst on a given axis we cannot
+    // stretch properly so just draw the bitmap as best as possible and return
+    if (bitmap.width() >= bounds.width() || bitmap.height() >= bounds.height())
+    {
+        canvas->drawBitmapRect(bitmap, NULL, bounds, paint);
+        return;
+    }
+
     // should try a quick-reject test before calling lockPixels 
 
     SkAutoLockPixels alp(bitmap);
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
index 4c84324..488b5c24 100644
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ b/core/jni/android_bluetooth_BluetoothSocket.cpp
@@ -57,6 +57,9 @@
 
 static const int RFCOMM_SO_SNDBUF = 70 * 1024;  // 70 KB send buffer
 
+static void abortNative(JNIEnv *env, jobject obj);
+static void destroyNative(JNIEnv *env, jobject obj);
+
 static struct asocket *get_socketData(JNIEnv *env, jobject obj) {
     struct asocket *s =
             (struct asocket *) env->GetIntField(obj, field_mSocketData);
@@ -172,6 +175,7 @@
     socklen_t addr_sz;
     struct sockaddr *addr;
     struct asocket *s = get_socketData(env, obj);
+    int retry = 0;
 
     if (!s)
         return;
@@ -226,10 +230,30 @@
         return;
     }
 
+connect:
     ret = asocket_connect(s, addr, addr_sz, -1);
     LOGV("...connect(%d, %s) = %d (errno %d)",
             s->fd, TYPE_AS_STR(type), ret, errno);
 
+    if (ret && errno == EALREADY && retry < 2) {
+        /* workaround for bug 5082381 (EALREADY on ACL collision):
+         * retry the connect. Unfortunately we have to create a new fd.
+         * It's not ideal to switch the fd underneath the object, but
+         * is currently safe */
+        LOGD("Hit bug 5082381 (EALREADY on ACL collision), trying workaround");
+        usleep(100000);
+        retry++;
+        abortNative(env, obj);
+        destroyNative(env, obj);
+        initSocketNative(env, obj);
+        if (env->ExceptionOccurred()) {
+            return;
+        }
+        goto connect;
+    }
+    if (!ret && retry > 0)
+        LOGD("...workaround ok");
+
     if (ret)
         jniThrowIOException(env, errno);
 
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 553632b..24d5d8d 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -21,7 +21,7 @@
     <!-- Height of the status bar -->
     <dimen name="status_bar_height">48dip</dimen>
     <!-- Width and height of a single notification icon in the status bar -->
-    <dimen name="status_bar_icon_size">32dip</dimen>
+    <dimen name="status_bar_icon_size">24dip</dimen>
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
 
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 3a3c082..3f4dace 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -132,10 +132,9 @@
 
 LOCAL_STATIC_LIBRARIES += \
         libstagefright_chromium_http \
-        libchromium_net         \
         libwebcore              \
 
-LOCAL_SHARED_LIBRARIES += libstlport
+LOCAL_SHARED_LIBRARIES += libstlport libchromium_net
 include external/stlport/libstlport.mk
 
 LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
index 08dcfae..3668b8c 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
@@ -21,7 +21,7 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:layout_width="fill_parent" 
                 android:layout_height="wrap_content"
-                android:padding="10dp" >
+                android:padding="16dp" >
 
     <TextView android:id="@+id/confirm_text"
               android:layout_width="match_parent" 
@@ -34,12 +34,26 @@
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:layout_marginBottom="10dp"
-              android:text="@string/backup_password_text" />
+              android:text="@string/current_password_text" />
 
     <EditText android:id="@+id/password"
               android:layout_below="@id/password_desc"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
+              android:layout_marginBottom="10dp"
+              android:password="true" />
+
+    <TextView android:id="@+id/enc_password_desc"
+              android:layout_below="@id/password"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:layout_marginBottom="10dp"
+              android:text="@string/backup_enc_password_text" />
+
+    <EditText android:id="@+id/enc_password"
+              android:layout_below="@id/enc_password_desc"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
               android:layout_marginBottom="30dp"
               android:password="true" />
 
@@ -47,7 +61,7 @@
               android:layout_width="match_parent"
               android:layout_height="20dp"
               android:layout_marginLeft="30dp"
-              android:layout_below="@id/password"
+              android:layout_below="@id/enc_password"
               android:layout_marginBottom="30dp" />
 
     <Button android:id="@+id/button_allow"
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
index 8b12ed4..38fcc496 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
@@ -21,7 +21,7 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:layout_width="fill_parent" 
                 android:layout_height="wrap_content"
-                android:padding="10dp" >
+                android:padding="16dp" >
 
     <TextView android:id="@+id/confirm_text"
               android:layout_width="match_parent" 
@@ -34,7 +34,7 @@
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:layout_marginBottom="10dp"
-              android:text="@string/restore_password_text" />
+              android:text="@string/current_password_text" />
 
     <EditText android:id="@+id/password"
               android:layout_below="@id/password_desc"
@@ -43,11 +43,25 @@
               android:layout_marginBottom="30dp"
               android:password="true" />
 
+    <TextView android:id="@+id/enc_password_desc"
+              android:layout_below="@id/password"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:layout_marginBottom="10dp"
+              android:text="@string/restore_enc_password_text" />
+
+    <EditText android:id="@+id/enc_password"
+              android:layout_below="@id/enc_password_desc"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:layout_marginBottom="30dp"
+              android:password="true" />
+
     <TextView android:id="@+id/package_name"
               android:layout_width="match_parent"
               android:layout_height="20dp"
               android:layout_marginLeft="30dp"
-              android:layout_below="@id/password"
+              android:layout_below="@id/enc_password"
               android:layout_marginBottom="30dp" />
 
     <Button android:id="@+id/button_allow"
diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index 48a8df6..f022e57 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -30,10 +30,13 @@
     <string name="deny_restore_button_label">Do not restore</string>
 
     <!-- Text for message to user that they must enter their predefined backup password in order to perform this operation. -->
-    <string name="backup_password_text">Please enter your predefined backup password below. The full backup will also be encrypted using this password:</string>
+    <string name="current_password_text">Please enter your current backup password below:</string>
+
+    <!-- Text for message to user that they can must enter an encryption password to use for the full backup operation. -->
+    <string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string>
     <!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
-    <string name="backup_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
+    <string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
 
     <!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
-    <string name="restore_password_text">If the backup data is encrypted, please enter the password below:</string>
+    <string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string>
 </resources>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index fad58b9..f65a62f 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -63,6 +63,8 @@
     boolean mDidAcknowledge;
 
     TextView mStatusView;
+    TextView mCurPassword;
+    TextView mEncPassword;
     Button mAllowButton;
     Button mDenyButton;
 
@@ -156,17 +158,17 @@
         mAllowButton = (Button) findViewById(R.id.button_allow);
         mDenyButton = (Button) findViewById(R.id.button_deny);
 
-        // For full backup, we vary the password prompt text depending on whether one is predefined
-        if (layoutId == R.layout.confirm_backup) {
-            TextView pwDesc = (TextView) findViewById(R.id.password_desc); 
-            try {
-                if (mBackupManager.hasBackupPassword()) {
-                    pwDesc.setText(R.string.backup_password_text);
-                } else {
-                    pwDesc.setText(R.string.backup_password_optional);
-                }
-            } catch (RemoteException e) {
-                // TODO: bail gracefully
+        mCurPassword = (TextView) findViewById(R.id.password);
+        mEncPassword = (TextView) findViewById(R.id.enc_password);
+        TextView curPwDesc = (TextView) findViewById(R.id.password_desc);
+
+        // We vary the password prompt depending on whether one is predefined
+        if (!haveBackupPassword()) {
+            curPwDesc.setVisibility(View.GONE);
+            mCurPassword.setVisibility(View.GONE);
+            if (layoutId == R.layout.confirm_backup) {
+                TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
+                encPwDesc.setText(R.string.backup_enc_password_optional);
             }
         }
 
@@ -204,15 +206,25 @@
             mDidAcknowledge = true;
 
             try {
-                TextView pwView = (TextView) findViewById(R.id.password);
-                mBackupManager.acknowledgeFullBackupOrRestore(mToken, allow,
-                        String.valueOf(pwView.getText()), mObserver);
+                mBackupManager.acknowledgeFullBackupOrRestore(mToken,
+                        allow,
+                        String.valueOf(mCurPassword.getText()),
+                        String.valueOf(mEncPassword.getText()),
+                        mObserver);
             } catch (RemoteException e) {
                 // TODO: bail gracefully if we can't contact the backup manager
             }
         }
     }
 
+    boolean haveBackupPassword() {
+        try {
+            return mBackupManager.hasBackupPassword();
+        } catch (RemoteException e) {
+            return true;        // in the failure case, assume we need one
+        }
+    }
+
     /**
      * The observer binder for showing backup/restore progress.  This binder just bounces
      * the notifications onto the main thread.
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 5e48461..fe5b983 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -4,3 +4,12 @@
   public void recentButtonClicked(android.view.View);
   public void toggleLightsOut(android.view.View);
 }
+
+-keep class com.android.systemui.statusbar.policy.KeyButtonView {
+  public float getDrawingAlpha();
+  public float getGlowAlpha();
+  public float getGlowScale();
+  public void setDrawingAlpha(float);
+  public void setGlowAlpha(float);
+  public void setGlowScale(float);
+}
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
index 7f96b03..ac5a97b 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
deleted file mode 100644
index ac5a97b..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png
rename to packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_pressed.png
deleted file mode 100644
index 8436f5a..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png
new file mode 100644
index 0000000..d050b1c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
index c43a019..a90dc9b 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
deleted file mode 100644
index a90dc9b..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png
rename to packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_pressed.png
deleted file mode 100644
index 83068a9..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
index 7af5454..d23f9b7 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
deleted file mode 100644
index d23f9b7..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png
rename to packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_pressed.png
deleted file mode 100644
index 56a4a1d..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
index 2d80bb9..cb3c433 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
deleted file mode 100644
index cb3c433..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png
rename to packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_pressed.png
deleted file mode 100644
index afc4057..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
rename to packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png
rename to packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png
deleted file mode 100644
index 83a8b26..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png
new file mode 100644
index 0000000..6f3f5fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
rename to packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png
rename to packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png
deleted file mode 100644
index b090b95..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
rename to packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png
rename to packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png
deleted file mode 100644
index 1affd8f..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
rename to packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png
rename to packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png
deleted file mode 100644
index c9724fc..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
new file mode 100644
index 0000000..97a07fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back.xml b/packages/SystemUI/res/drawable/ic_sysbar_back.xml
deleted file mode 100644
index 327ccd8..0000000
--- a/packages/SystemUI/res/drawable/ic_sysbar_back.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_back_pressed" />
-    <item android:drawable="@drawable/ic_sysbar_back_default" />
-</selector>
-
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_home.xml b/packages/SystemUI/res/drawable/ic_sysbar_home.xml
deleted file mode 100644
index f4e585e..0000000
--- a/packages/SystemUI/res/drawable/ic_sysbar_home.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_home_pressed" />
-    <item android:drawable="@drawable/ic_sysbar_home_default" />
-</selector>
-
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
deleted file mode 100644
index 7a10607..0000000
--- a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_menu_pressed" />
-    <item android:drawable="@drawable/ic_sysbar_menu_default" />
-</selector>
-
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_recent.xml b/packages/SystemUI/res/drawable/ic_sysbar_recent.xml
deleted file mode 100755
index 39a324b..0000000
--- a/packages/SystemUI/res/drawable/ic_sysbar_recent.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_recent_pressed" />
-    <item android:drawable="@drawable/ic_sysbar_recent_default" />
-</selector>
-
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar.xml b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
index a2a6473..a204f17 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
@@ -32,6 +32,7 @@
             android:id="@+id/bar_contents"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:clipChildren="false"
             >
 
             <!-- notification icons & panel access -->
@@ -50,6 +51,7 @@
                 android:layout_alignParentLeft="true"
                 systemui:keyCode="4"
                 android:contentDescription="@string/accessibility_back"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
                 />
             <LinearLayout
                 android:id="@+id/navigationArea"
@@ -57,6 +59,8 @@
                 android:layout_height="match_parent"
                 android:layout_toRightOf="@+id/back"
                 android:orientation="horizontal"
+                android:clipChildren="false"
+                android:clipToPadding="false"
                 >
                 <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
                     android:layout_width="80dip"
@@ -64,12 +68,14 @@
                     android:src="@drawable/ic_sysbar_home"
                     systemui:keyCode="3"
                     android:contentDescription="@string/accessibility_home"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight"
                     />
-                <ImageView android:id="@+id/recent_apps"
+                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
                     android:layout_width="80dip"
                     android:layout_height="match_parent"
                     android:src="@drawable/ic_sysbar_recent"
                     android:contentDescription="@string/accessibility_menu"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight"
                     />
                 <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
                     android:layout_width="80dip"
@@ -78,6 +84,7 @@
                     systemui:keyCode="82"
                     android:visibility="invisible"
                     android:contentDescription="@string/accessibility_menu"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight"
                     />
             </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 5d7e8de..6732fee 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -35,6 +35,8 @@
             android:layout_height="match_parent"
             android:layout_width="match_parent"
             android:orientation="horizontal"
+            android:clipChildren="false"
+            android:clipToPadding="false"
             >
 
             <!-- navigation controls -->
@@ -42,47 +44,55 @@
                 android:layout_width="40dp"
                 android:layout_height="match_parent"
                 android:layout_weight="0"
+                android:visibility="invisible"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
                 android:layout_width="80dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_back_default"
+                android:src="@drawable/ic_sysbar_back"
                 systemui:keyCode="4"
                 android:layout_weight="0"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_back"
                 />
             <View 
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
-                android:contentDescription="@string/accessibility_back"
+                android:visibility="invisible"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
                 android:layout_width="80dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_home_default"
+                android:src="@drawable/ic_sysbar_home"
                 systemui:keyCode="3"
                 android:layout_weight="0"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_home"
                 />
             <View 
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
-                android:contentDescription="@string/accessibility_home"
+                android:visibility="invisible"
                 />
-            <ImageView android:id="@+id/recent_apps"
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
                 android:layout_width="80dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_recent_default"
+                android:src="@drawable/ic_sysbar_recent"
                 android:layout_weight="0"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_recent"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
                 android:layout_width="40dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_menu_default"
+                android:src="@drawable/ic_sysbar_menu"
                 systemui:keyCode="82"
                 android:layout_weight="0"
                 android:visibility="invisible"
                 android:contentDescription="@string/accessibility_menu"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
                 />
         </LinearLayout>
 
@@ -106,55 +116,66 @@
             android:layout_height="match_parent"
             android:layout_width="match_parent"
             android:orientation="vertical"
+            android:clipChildren="false"
+            android:clipToPadding="false"
             >
             
             <!-- navigation controls -->
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
                 android:layout_height="40dp"
                 android:layout_width="match_parent"
-                android:src="@drawable/ic_sysbar_menu_default_land"
+                android:src="@drawable/ic_sysbar_menu_land"
                 systemui:keyCode="82"
                 android:layout_weight="0"
                 android:visibility="invisible"
                 />
-            <ImageView android:id="@+id/recent_apps"
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
                 android:layout_height="80dp"
                 android:layout_width="match_parent"
-                android:src="@drawable/ic_sysbar_recent_default_land"
+                android:src="@drawable/ic_sysbar_recent_land"
                 android:layout_weight="0"
+                android:contentDescription="@string/accessibility_recent"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
                 />
             <View 
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
                 android:layout_weight="1"
-                android:contentDescription="@string/accessibility_menu"
+                android:visibility="invisible"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
                 android:layout_height="80dp"
                 android:layout_width="match_parent"
-                android:src="@drawable/ic_sysbar_home_default_land"
+                android:src="@drawable/ic_sysbar_home_land"
                 systemui:keyCode="3"
                 android:layout_weight="0"
                 android:contentDescription="@string/accessibility_home"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
                 />
             <View 
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
                 android:layout_weight="1"
-                android:contentDescription="@string/accessibility_back"
+                android:visibility="invisible"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
                 android:layout_height="80dp"
                 android:layout_width="match_parent"
-                android:src="@drawable/ic_sysbar_back_default_land"
+                android:src="@drawable/ic_sysbar_back_land"
                 systemui:keyCode="4"
                 android:layout_weight="0"
+                android:contentDescription="@string/accessibility_back"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
                 />
-            <View
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
                 android:layout_height="40dp"
                 android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_menu_land"
+                systemui:keyCode="82"
                 android:layout_weight="0"
+                android:visibility="invisible"
                 android:contentDescription="@string/accessibility_menu"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
                 />
         </LinearLayout>
 
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 5291629..b2b6d50 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -17,6 +17,7 @@
 <resources>
     <declare-styleable name="KeyButtonView">
         <attr name="keyCode" format="integer" />
+        <attr name="glowBackground" format="reference" />
     </declare-styleable>
     <declare-styleable name="ToggleSlider">
         <attr name="text" format="string" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5ca77fc..2b3118d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -185,6 +185,8 @@
     <string name="accessibility_home">Home</string>
     <!-- Content description of the menu button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_menu">Menu</string>
+    <!-- Content description of the recents button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_recent">Recent applications</string>
 
     <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_ime_switch_button">Switch input method button.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index eaffd1a..6ecfd94 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -131,9 +131,16 @@
         return result;
     }
 
-    void invalidateGlobalRegion(View view) {
-        RectF childBounds = new RectF(view.getLeft(), view.getTop(), view.getRight(), view
-                .getBottom());
+    // invalidate the view's own bounds all the way up the view hierarchy
+    public static void invalidateGlobalRegion(View view) {
+        invalidateGlobalRegion(
+            view,
+            new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()));
+    }
+
+    // invalidate a rectangle relative to the view's coordinate system all the way up the view
+    // hierarchy
+    public static void invalidateGlobalRegion(View view, RectF childBounds) {
         childBounds.offset(view.getX(), view.getY());
         if (DEBUG_INVALIDATE)
             Log.v(TAG, "-------------");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 62d7500..c91f513 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -54,7 +54,7 @@
     private static final int OP_EXPAND      = 1;
     private static final int OP_COLLAPSE    = 2;
 
-    private static final int MSG_SET_LIGHTS_ON          = 7 << MSG_SHIFT;
+    private static final int MSG_SET_SYSTEMUI_VISIBILITY          = 7 << MSG_SHIFT;
 
     private static final int MSG_TOP_APP_WINDOW_CHANGED = 8 << MSG_SHIFT;
     private static final int MSG_SHOW_IME_BUTTON        = 9 << MSG_SHIFT;
@@ -86,7 +86,7 @@
         public void disable(int state);
         public void animateExpand();
         public void animateCollapse();
-        public void setLightsOn(boolean on);
+        public void setSystemUiVisibility(int vis);
         public void topAppWindowChanged(boolean visible);
         public void setImeWindowStatus(IBinder token, int vis, int backDisposition);
         public void setHardKeyboardStatus(boolean available, boolean enabled);
@@ -160,10 +160,10 @@
         }
     }
 
-    public void setLightsOn(boolean on) {
+    public void setSystemUiVisibility(int vis) {
         synchronized (mList) {
-            mHandler.removeMessages(MSG_SET_LIGHTS_ON);
-            mHandler.obtainMessage(MSG_SET_LIGHTS_ON, on ? 1 : 0, 0, null).sendToTarget();
+            mHandler.removeMessages(MSG_SET_SYSTEMUI_VISIBILITY);
+            mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, vis, 0, null).sendToTarget();
         }
     }
 
@@ -259,8 +259,8 @@
                         mCallbacks.animateCollapse();
                     }
                     break;
-                case MSG_SET_LIGHTS_ON:
-                    mCallbacks.setLightsOn(msg.arg1 != 0);
+                case MSG_SET_SYSTEMUI_VISIBILITY:
+                    mCallbacks.setSystemUiVisibility(msg.arg1);
                     break;
                 case MSG_TOP_APP_WINDOW_CHANGED:
                     mCallbacks.topAppWindowChanged(msg.arg1 != 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
index ca75138..918d5a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
@@ -78,7 +78,7 @@
         }
 
         disable(switches[0]);
-        setLightsOn(switches[1] != 0);
+        setSystemUiVisibility(switches[1]);
         topAppWindowChanged(switches[2] != 0);
         // StatusBarManagerService has a back up of IME token and it's restored here.
         setImeWindowStatus(binders.get(0), switches[3], switches[4]);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 550fc57..2740898 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -17,11 +17,14 @@
 package com.android.systemui.statusbar.phone;
 
 import android.animation.Animator;
+import android.animation.AnimatorSet;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.content.res.Resources;
 import android.os.ServiceManager;
 import android.util.AttributeSet;
+import android.util.Slog;
 import android.view.Display;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -36,6 +39,9 @@
 import com.android.systemui.R;
 
 public class NavigationBarView extends LinearLayout {
+    final static boolean DEBUG = false;
+    final static String TAG = "NavigationBarView";
+
     final static boolean DEBUG_DEADZONE = false;
 
     final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
@@ -44,7 +50,12 @@
     final Display mDisplay;
     View mCurrentView = null;
     View[] mRotatedViews = new View[4];
-    Animator mLastAnimator = null;
+    AnimatorSet mLastAnimator = null;
+
+    int mBarSize;
+    boolean mVertical;
+
+    boolean mHidden;
 
     public View getRecentsButton() {
         return mCurrentView.findViewById(R.id.recent_apps);
@@ -56,37 +67,53 @@
 
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mHidden = false;
+
         mDisplay = ((WindowManager)context.getSystemService(
                 Context.WINDOW_SERVICE)).getDefaultDisplay();
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
 
-        //setLayerType(View.LAYER_TYPE_HARDWARE, null);
-
-        setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
-            @Override
-            public void onSystemUiVisibilityChange(int visibility) {
-                boolean on = (visibility == View.STATUS_BAR_VISIBLE);
-                android.util.Log.d("NavigationBarView", "LIGHTS " 
-                    + (on ? "ON" : "OUT"));
-                setLights(on);
-            }
-        });
+        final Resources res = mContext.getResources();
+        mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
+        mVertical = false;
     }
 
-    private void setLights(final boolean on) {
+    public void setHidden(final boolean hide) {
+        if (hide == mHidden) return;
+
+        mHidden = hide;
+        Slog.d(TAG,
+            (hide ? "HIDING" : "SHOWING") + " navigation bar");
+
         float oldAlpha = mCurrentView.getAlpha();
-        android.util.Log.d("NavigationBarView", "animating alpha: " + oldAlpha + " -> "
-            + (on ? 1f : 0f));
+        if (DEBUG) {
+            Slog.d(TAG, "animating alpha: " + oldAlpha + " -> "
+                + (!hide ? 1f : 0f));
+        }
 
         if (mLastAnimator != null && mLastAnimator.isRunning()) mLastAnimator.cancel();
 
-        mLastAnimator = ObjectAnimator.ofFloat(mCurrentView, "alpha", oldAlpha, on ? 1f : 0f)
-            .setDuration(on ? 250 : 1500);
+        if (!hide) {
+            setVisibility(View.VISIBLE);
+        }
+
+        // play us off, animatorset
+        mLastAnimator = new AnimatorSet();
+        mLastAnimator.playTogether(
+                ObjectAnimator.ofFloat(mCurrentView, "alpha", hide ? 0f : 1f),
+                ObjectAnimator.ofFloat(mCurrentView,
+                                       mVertical ? "translationX" : "translationY",
+                                       hide ? mBarSize : 0)
+        );
+        mLastAnimator.setDuration(!hide ? 250 : 1000);
         mLastAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator _a) {
                 mLastAnimator = null;
+                if (hide) {
+                    setVisibility(View.INVISIBLE);
+                }
             }
         });
         mLastAnimator.start();
@@ -108,7 +135,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         // immediately bring up the lights
-        setLights(true);
+        setHidden(false);
         return false; // pass it on
     }
 
@@ -119,11 +146,14 @@
         }
         mCurrentView = mRotatedViews[rot];
         mCurrentView.setVisibility(View.VISIBLE);
+        mVertical = (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270);
 
         if (DEBUG_DEADZONE) {
             mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
         }
 
-        android.util.Log.d("NavigationBarView", "reorient(): rot=" + mDisplay.getRotation());
+        if (DEBUG) {
+            Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 21b774c..f8ceb8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -198,6 +198,9 @@
     // for disabling the status bar
     int mDisabled = 0;
 
+    // tracking calls to View.setSystemUiVisibility()
+    int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+
     private class ExpandedDialog extends Dialog {
         ExpandedDialog(Context context) {
             super(context, com.android.internal.R.style.Theme_Light_NoTitleBar);
@@ -253,20 +256,33 @@
         mIntruderAlertView.setVisibility(View.GONE);
         mIntruderAlertView.setClickable(true);
 
+        PhoneStatusBarView sb = (PhoneStatusBarView)View.inflate(context,
+                R.layout.status_bar, null);
+        sb.mService = this;
+        mStatusBarView = sb;
+
         try {
             boolean showNav = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
             if (showNav) {
                 mNavigationBarView = 
                     (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
+
+                sb.setOnSystemUiVisibilityChangeListener(
+                    new View.OnSystemUiVisibilityChangeListener() {
+                        @Override
+                        public void onSystemUiVisibilityChange(int visibility) {
+                            if (DEBUG) {
+                                Slog.d(TAG, "systemUi: " + visibility);
+                            }
+                            boolean hide = (0 != (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION));
+                            mNavigationBarView.setHidden(hide);
+                        }
+                    });
             }
         } catch (Resources.NotFoundException ex) {
             // no nav bar for you
         }
 
-        PhoneStatusBarView sb = (PhoneStatusBarView)View.inflate(context,
-                R.layout.status_bar, null);
-        sb.mService = this;
-
         // figure out which pixel-format to use for the status bar.
         mPixelFormat = PixelFormat.TRANSLUCENT;
         Drawable bg = sb.getBackground();
@@ -274,7 +290,6 @@
             mPixelFormat = bg.getOpacity();
         }
 
-        mStatusBarView = sb;
         mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);
         mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons);
         mIcons = (LinearLayout)sb.findViewById(R.id.icons);
@@ -649,8 +664,10 @@
                 if (notification.notification.largeIcon != null) {
                     oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon);
                 } else {
-                    oldEntry.largeIcon.getLayoutParams().width = 0;
-                    oldEntry.largeIcon.setVisibility(View.INVISIBLE);
+                    if (oldEntry.largeIcon != null) {
+                        oldEntry.largeIcon.getLayoutParams().width = 0;
+                        oldEntry.largeIcon.setVisibility(View.INVISIBLE);
+                    }
                 }
 
             }
@@ -1275,22 +1292,31 @@
         return false;
     }
 
-    public void setLightsOn(boolean on) {
-        Log.v(TAG, "lights " + (on ? "on" : "off"));
-        if (!on) {
-            // All we do for "lights out" mode on a phone is hide the status bar,
-            // which the window manager does.  But we do need to hide the windowshade
-            // on our own.
-            animateCollapse();
+    @Override // CommandQueue
+    public void setSystemUiVisibility(int vis) {
+        if (vis != mSystemUiVisibility) {
+            mSystemUiVisibility = vis;
+
+            if (0 != (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE)) {
+                animateCollapse();
+            }
+
+            notifyUiVisibilityChanged();
         }
-        notifyLightsChanged(on);
     }
 
-    private void notifyLightsChanged(boolean shown) {
+    public void setLightsOn(boolean on) {
+        Log.v(TAG, "setLightsOn(" + on + ")");
+        if (on) {
+            setSystemUiVisibility(mSystemUiVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
+        } else {
+            setSystemUiVisibility(mSystemUiVisibility | View.SYSTEM_UI_FLAG_LOW_PROFILE);
+        }
+    }
+
+    private void notifyUiVisibilityChanged() {
         try {
-            Slog.d(TAG, "lights " + (shown?"on":"out"));
-            mWindowManager.statusBarVisibilityChanged(
-                    shown ? View.STATUS_BAR_VISIBLE : View.STATUS_BAR_HIDDEN);
+            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
         } catch (RemoteException ex) {
         }
     }
@@ -1715,10 +1741,12 @@
         }
     }
 
+    // The user is not allowed to get stuck without navigation UI. Upon the slightest user
+    // interaction we bring the navigation back.
     public void userActivity() {
-        try {
-            mBarService.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
-        } catch (RemoteException ex) { }
+        if (mNavigationBarView != null) {
+            mNavigationBarView.setHidden(false);
+        }
     }
 
     public void toggleRecentApps() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index c82220d..38a1029 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -16,10 +16,15 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.Canvas;
+import android.graphics.RectF;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.ServiceManager;
@@ -33,7 +38,9 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SoundEffectConstants;
+import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.RemoteViews.RemoteView;
 
@@ -48,18 +55,25 @@
     int mCode;
     int mRepeat;
     int mTouchSlop;
+    Drawable mGlowBG;
+    float mGlowAlpha = 0f, mGlowScale = 1f, mDrawingAlpha = 1f;
 
     Runnable mCheckLongPress = new Runnable() {
         public void run() {
             if (isPressed()) {
-                mRepeat++;
-                sendEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.FLAG_FROM_SYSTEM
-                        | KeyEvent.FLAG_VIRTUAL_HARD_KEY
-                        | KeyEvent.FLAG_LONG_PRESS);
 
-                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
-                //playSoundEffect(SoundEffectConstants.CLICK);
+                if (mCode != 0) {
+                    mRepeat++;
+                    sendEvent(KeyEvent.ACTION_DOWN,
+                            KeyEvent.FLAG_FROM_SYSTEM
+                            | KeyEvent.FLAG_VIRTUAL_HARD_KEY
+                            | KeyEvent.FLAG_LONG_PRESS);
+
+                    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+                } else {
+                    // Just an old-fashioned ImageView
+                    performLongClick();
+                }
             }
         }
     };
@@ -75,8 +89,10 @@
                 defStyle, 0);
 
         mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0);
-        if (mCode == 0) {
-            Slog.w(TAG, "KeyButtonView without key code id=0x" + Integer.toHexString(getId()));
+
+        mGlowBG = a.getDrawable(R.styleable.KeyButtonView_glowBackground);
+        if (mGlowBG != null) {
+            mDrawingAlpha = 0.5f;
         }
         
         a.recycle();
@@ -88,6 +104,99 @@
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
     }
 
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mGlowBG != null) {
+            canvas.save();
+            final int w = getWidth();
+            final int h = getHeight();
+            canvas.scale(mGlowScale, mGlowScale, w*0.5f, h*0.5f);
+            mGlowBG.setBounds(0, 0, w, h);
+            mGlowBG.setAlpha((int)(mGlowAlpha * 255));
+            mGlowBG.draw(canvas);
+            canvas.restore();
+
+            canvas.saveLayerAlpha(null, (int)(mDrawingAlpha * 255), Canvas.ALL_SAVE_FLAG);
+        }
+        super.onDraw(canvas);
+        if (mGlowBG != null) {
+            canvas.restore();
+        }
+    }
+
+    public float getDrawingAlpha() {
+        if (mGlowBG == null) return 0;
+        return mDrawingAlpha;
+    }
+
+    public void setDrawingAlpha(float x) {
+        if (mGlowBG == null) return;
+        mDrawingAlpha = x;
+        invalidate();
+    }
+
+    public float getGlowAlpha() {
+        if (mGlowBG == null) return 0;
+        return mGlowAlpha;
+    }
+
+    public void setGlowAlpha(float x) {
+        if (mGlowBG == null) return;
+        mGlowAlpha = x;
+        invalidate();
+    }
+
+    public float getGlowScale() {
+        if (mGlowBG == null) return 0;
+        return mGlowScale;
+    }
+
+    public void setGlowScale(float x) {
+        if (mGlowBG == null) return;
+        mGlowScale = x;
+        final float w = getWidth();
+        final float h = getHeight();
+        if (x < 1.0f) {
+            invalidate();
+        } else {
+            final float rx = (w * (x - 1.0f)) / 2.0f;
+            final float ry = (h * (x - 1.0f)) / 2.0f;
+            com.android.systemui.SwipeHelper.invalidateGlobalRegion(
+                    this,
+                    new RectF(getLeft() - rx,
+                              getTop() - ry,
+                              getRight() + rx,
+                              getBottom() + ry));
+        }
+    }
+
+    public void setPressed(boolean pressed) {
+        if (mGlowBG != null) {
+            if (pressed != isPressed()) {
+                AnimatorSet as = new AnimatorSet();
+                if (pressed) {
+                    if (mGlowScale < 1.7f) mGlowScale = 1.7f;
+                    if (mGlowAlpha < 0.5f) mGlowAlpha = 0.5f;
+                    setDrawingAlpha(1f);
+                    as.playTogether(
+                        ObjectAnimator.ofFloat(this, "glowAlpha", 1f),
+                        ObjectAnimator.ofFloat(this, "glowScale", 1.8f)
+                    );
+                    as.setDuration(50);
+                } else {
+                    as.playTogether(
+                        ObjectAnimator.ofFloat(this, "glowAlpha", 0f),
+                        ObjectAnimator.ofFloat(this, "glowScale", 1f),
+                        ObjectAnimator.ofFloat(this, "drawingAlpha", 0.5f)
+                    );
+                    as.setDuration(500);
+                }
+                as.start();
+            }
+        }
+        super.setPressed(pressed);
+    }
+
     public boolean onTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
         int x, y;
@@ -131,12 +240,18 @@
                     mSending = false;
                     final int flags = KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY;
                     removeCallbacks(mCheckLongPress);
-                    if (doIt) {
-                        sendEvent(KeyEvent.ACTION_UP, flags);
-                        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
-                        playSoundEffect(SoundEffectConstants.CLICK);
+
+                    if (mCode != 0) {
+                        if (doIt) {
+                            sendEvent(KeyEvent.ACTION_UP, flags);
+                            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+                            playSoundEffect(SoundEffectConstants.CLICK);
+                        } else {
+                            sendEvent(KeyEvent.ACTION_UP, flags | KeyEvent.FLAG_CANCELED);
+                        }
                     } else {
-                        sendEvent(KeyEvent.ACTION_UP, flags | KeyEvent.FLAG_CANCELED);
+                        // no key code, just a regular ImageView
+                        if (doIt) performClick();
                     }
                 }
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 96f6e2f..c6e546e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -176,6 +176,8 @@
     private InputMethodsPanel mInputMethodsPanel;
     private CompatModePanel mCompatModePanel;
 
+    int mSystemUiVisibility = 0;
+
     public Context getContext() { return mContext; }
 
     protected void addPanelWindows() {
@@ -729,14 +731,16 @@
                     if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
                     mBarContents.setVisibility(View.VISIBLE);
                     mShadow.setVisibility(View.GONE);
-                    notifyLightsChanged(true);
+                    mSystemUiVisibility &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
+                    notifyUiVisibilityChanged();
                     break;
                 case MSG_HIDE_CHROME:
                     if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
                     animateCollapse();
                     mBarContents.setVisibility(View.GONE);
                     mShadow.setVisibility(View.VISIBLE);
-                    notifyLightsChanged(false);
+                    mSystemUiVisibility |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
+                    notifyUiVisibilityChanged();
                     break;
                 case MSG_STOP_TICKER:
                     mTicker.halt();
@@ -1025,17 +1029,40 @@
         mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
     }
 
-    // called by StatusBar
-    @Override
+    private void notifyUiVisibilityChanged() {
+        try {
+            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+        } catch (RemoteException ex) {
+        }
+    }
+
+    @Override // CommandQueue
+    public void setSystemUiVisibility(int vis) {
+        if (vis != mSystemUiVisibility) {
+            mSystemUiVisibility = vis;
+
+            mHandler.removeMessages(MSG_HIDE_CHROME);
+            mHandler.removeMessages(MSG_SHOW_CHROME);
+            mHandler.sendEmptyMessage(0 == (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) 
+                    ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
+
+            notifyUiVisibilityChanged();
+        }
+    }
+
     public void setLightsOn(boolean on) {
         // Policy note: if the frontmost activity needs the menu key, we assume it is a legacy app
         // that can't handle lights-out mode.
         if (mMenuButton.getVisibility() == View.VISIBLE) {
             on = true;
         }
-        mHandler.removeMessages(MSG_HIDE_CHROME);
-        mHandler.removeMessages(MSG_SHOW_CHROME);
-        mHandler.sendEmptyMessage(on ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
+
+        Slog.v(TAG, "setLightsOn(" + on + ")");
+        if (on) {
+            setSystemUiVisibility(mSystemUiVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
+        } else {
+            setSystemUiVisibility(mSystemUiVisibility | View.SYSTEM_UI_FLAG_LOW_PROFILE);
+        }
     }
 
     public void topAppWindowChanged(boolean showMenu) {
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 3ec2a96..bdd8938 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -307,7 +307,8 @@
         public ParcelFileDescriptor fd;
         public final AtomicBoolean latch;
         public IFullBackupRestoreObserver observer;
-        public String password;     // filled in by the confirmation step
+        public String curPassword;     // filled in by the confirmation step
+        public String encryptPassword;
 
         FullParams() {
             latch = new AtomicBoolean(false);
@@ -458,8 +459,8 @@
             {
                 FullBackupParams params = (FullBackupParams)msg.obj;
                 (new PerformFullBackupTask(params.fd, params.observer, params.includeApks,
-                        params.includeShared, params.password, params.allApps, params.packages,
-                        params.latch)).run();
+                        params.includeShared, params.curPassword, params.encryptPassword,
+                        params.allApps, params.packages, params.latch)).run();
                 break;
             }
 
@@ -476,7 +477,7 @@
             case MSG_RUN_FULL_RESTORE:
             {
                 FullRestoreParams params = (FullRestoreParams)msg.obj;
-                (new PerformFullRestoreTask(params.fd, params.password,
+                (new PerformFullRestoreTask(params.fd, params.curPassword, params.encryptPassword,
                         params.observer, params.latch)).run();
                 break;
             }
@@ -1908,7 +1909,8 @@
         boolean mIncludeShared;
         boolean mAllApps;
         String[] mPackages;
-        String mUserPassword;
+        String mCurrentPassword;
+        String mEncryptPassword;
         AtomicBoolean mLatchObject;
         File mFilesDir;
         File mManifestFile;
@@ -1963,15 +1965,25 @@
         }
 
         PerformFullBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer, 
-                boolean includeApks, boolean includeShared, String password,
-                boolean doAllApps, String[] packages, AtomicBoolean latch) {
+                boolean includeApks, boolean includeShared, String curPassword,
+                String encryptPassword, boolean doAllApps, String[] packages,
+                AtomicBoolean latch) {
             mOutputFile = fd;
             mObserver = observer;
             mIncludeApks = includeApks;
             mIncludeShared = includeShared;
             mAllApps = doAllApps;
             mPackages = packages;
-            mUserPassword = password;
+            mCurrentPassword = curPassword;
+            // when backing up, if there is a current backup password, we require that
+            // the user use a nonempty encryption password as well.  if one is supplied
+            // in the UI we use that, but if the UI was left empty we fall back to the
+            // current backup password (which was supplied by the user as well).
+            if (encryptPassword == null || "".equals(encryptPassword)) {
+                mEncryptPassword = curPassword;
+            } else {
+                mEncryptPassword = encryptPassword;
+            }
             mLatchObject = latch;
 
             mFilesDir = new File("/data/system");
@@ -2016,7 +2028,7 @@
 
             PackageInfo pkg = null;
             try {
-                boolean encrypting = (mUserPassword != null && mUserPassword.length() > 0);
+                boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0);
                 boolean compressing = COMPRESS_FULL_BACKUPS;
                 OutputStream finalOutput = ofstream;
 
@@ -2057,7 +2069,7 @@
                         // Verify that the given password matches the currently-active
                         // backup password, if any
                         if (hasBackupPassword()) {
-                            if (!passwordMatchesSaved(mUserPassword, PBKDF2_HASH_ROUNDS)) {
+                            if (!passwordMatchesSaved(mCurrentPassword, PBKDF2_HASH_ROUNDS)) {
                                 if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
                                 return;
                             }
@@ -2122,7 +2134,7 @@
                 OutputStream ofstream) throws Exception {
             // User key will be used to encrypt the master key.
             byte[] newUserSalt = randomBytes(PBKDF2_SALT_SIZE);
-            SecretKey userKey = buildPasswordKey(mUserPassword, newUserSalt,
+            SecretKey userKey = buildPasswordKey(mEncryptPassword, newUserSalt,
                     PBKDF2_HASH_ROUNDS);
 
             // the master key is random for each backup
@@ -2445,7 +2457,8 @@
 
     class PerformFullRestoreTask implements Runnable {
         ParcelFileDescriptor mInputFile;
-        String mUserPassword;
+        String mCurrentPassword;
+        String mDecryptPassword;
         IFullBackupRestoreObserver mObserver;
         AtomicBoolean mLatchObject;
         IBackupAgent mAgent;
@@ -2469,10 +2482,11 @@
         // Packages we've already wiped data on when restoring their first file
         final HashSet<String> mClearedPackages = new HashSet<String>();
 
-        PerformFullRestoreTask(ParcelFileDescriptor fd, String password,
+        PerformFullRestoreTask(ParcelFileDescriptor fd, String curPassword, String decryptPassword,
                 IFullBackupRestoreObserver observer, AtomicBoolean latch) {
             mInputFile = fd;
-            mUserPassword = password;
+            mCurrentPassword = curPassword;
+            mDecryptPassword = decryptPassword;
             mObserver = observer;
             mLatchObject = latch;
             mAgent = null;
@@ -2531,6 +2545,13 @@
             FileInputStream rawInStream = null;
             DataInputStream rawDataIn = null;
             try {
+                if (hasBackupPassword()) {
+                    if (!passwordMatchesSaved(mCurrentPassword, PBKDF2_HASH_ROUNDS)) {
+                        if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
+                        return;
+                    }
+                }
+
                 mBytes = 0;
                 byte[] buffer = new byte[32 * 1024];
                 rawInStream = new FileInputStream(mInputFile.getFileDescriptor());
@@ -2557,7 +2578,7 @@
                         if (s.equals("none")) {
                             // no more header to parse; we're good to go
                             okay = true;
-                        } else if (mUserPassword != null && mUserPassword.length() > 0) {
+                        } else if (mDecryptPassword != null && mDecryptPassword.length() > 0) {
                             preCompressStream = decodeAesHeaderAndInitialize(s, rawInStream);
                             if (preCompressStream != null) {
                                 okay = true;
@@ -2635,7 +2656,7 @@
 
                     // decrypt the master key blob
                     Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
-                    SecretKey userKey = buildPasswordKey(mUserPassword, userSalt,
+                    SecretKey userKey = buildPasswordKey(mDecryptPassword, userSalt,
                             rounds);
                     byte[] IV = hexToByteArray(userIvHex);
                     IvParameterSpec ivSpec = new IvParameterSpec(IV);
@@ -4453,7 +4474,7 @@
     // is used to require a user-facing disclosure about the operation.
     @Override
     public void acknowledgeFullBackupOrRestore(int token, boolean allow,
-            String password, IFullBackupRestoreObserver observer) {
+            String curPassword, String encPpassword, IFullBackupRestoreObserver observer) {
         if (DEBUG) Slog.d(TAG, "acknowledgeFullBackupOrRestore : token=" + token
                 + " allow=" + allow);
 
@@ -4472,12 +4493,14 @@
                     mFullConfirmations.delete(token);
 
                     if (allow) {
-                        params.observer = observer;
-                        params.password = password;
                         final int verb = params instanceof FullBackupParams
                                 ? MSG_RUN_FULL_BACKUP
                                 : MSG_RUN_FULL_RESTORE;
 
+                        params.observer = observer;
+                        params.curPassword = curPassword;
+                        params.encryptPassword = encPpassword;
+
                         if (DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb);
                         mWakelock.acquire();
                         Message msg = mBackupHandler.obtainMessage(verb, params);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 9a9cc8f..2a724d4 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2484,7 +2484,7 @@
         synchronized (this) {
             if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
             if (mDefaultProxy == proxy) return;
-            if (!TextUtils.isEmpty(proxy.getHost())) {
+            if (proxy != null && !TextUtils.isEmpty(proxy.getHost())) {
                 mDefaultProxy = proxy;
             } else {
                 mDefaultProxy = null;
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 4ced83c..ca3b12d 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -69,8 +69,8 @@
     int mDisabled = 0;
 
     Object mLock = new Object();
-    // We usually call it lights out mode, but double negatives are annoying
-    boolean mLightsOn = true;
+    // encompasses lights-out mode and other flags defined on View
+    int mSystemUiVisibility = 0;
     boolean mMenuVisible = false;
     int mImeWindowVis = 0;
     int mImeBackDisposition;
@@ -301,22 +301,23 @@
         // also allows calls from window manager which is in this process.
         enforceStatusBarService();
 
+        if (SPEW) Slog.d(TAG, "setSystemUiVisibility(" + vis + ")");
+
         synchronized (mLock) {
-            final boolean lightsOn = (vis & View.STATUS_BAR_HIDDEN) == 0;
-            updateLightsOnLocked(lightsOn);
+            updateUiVisibilityLocked(vis);
             disableLocked(vis & StatusBarManager.DISABLE_MASK, mSysUiVisToken,
                     "WindowManager.LayoutParams");
         }
     }
 
-    private void updateLightsOnLocked(final boolean lightsOn) {
-        if (mLightsOn != lightsOn) {
-            mLightsOn = lightsOn;
+    private void updateUiVisibilityLocked(final int vis) {
+        if (mSystemUiVisibility != vis) {
+            mSystemUiVisibility = vis;
             mHandler.post(new Runnable() {
                     public void run() {
                         if (mBar != null) {
                             try {
-                                mBar.setLightsOn(lightsOn);
+                                mBar.setSystemUiVisibility(vis);
                             } catch (RemoteException ex) {
                             }
                         }
@@ -392,7 +393,7 @@
         }
         synchronized (mLock) {
             switches[0] = gatherDisableActionsLocked();
-            switches[1] = mLightsOn ? 1 : 0;
+            switches[1] = mSystemUiVisibility;
             switches[2] = mMenuVisible ? 1 : 0;
             switches[3] = mImeWindowVis;
             switches[4] = mImeBackDisposition;
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index b2d9917..837778e 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -73,6 +73,16 @@
         synchronized (mSpellCheckerMap) {
             buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap);
         }
+        SpellCheckerInfo sci = getCurrentSpellChecker(null);
+        if (sci == null) {
+            sci = findAvailSpellCheckerLocked(null, null);
+            if (sci != null) {
+                // Set the current spell checker if there is one or more spell checkers
+                // available. In this case, "sci" is the first one in the available spell
+                // checkers.
+                setCurrentSpellCheckerLocked(sci);
+            }
+        }
     }
 
     private class TextServicesMonitor extends PackageMonitor {
@@ -87,10 +97,10 @@
                 final int change = isPackageDisappearing(packageName);
                 if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
                     // Package disappearing
-                    setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
+                    setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName));
                 } else if (isPackageModified(packageName)) {
                     // Package modified
-                    setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
+                    setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName));
                 }
             }
         }
@@ -160,13 +170,7 @@
                 Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId);
             }
             if (TextUtils.isEmpty(curSpellCheckerId)) {
-                final SpellCheckerInfo sci = findAvailSpellCheckerLocked(null, null);
-                if (sci == null) return null;
-                // Set the current spell checker if there is one or more spell checkers
-                // available. In this case, "sci" is the first one in the available spell
-                // checkers.
-                setCurrentSpellChecker(sci);
-                return sci;
+                return null;
             }
             return mSpellCheckerMap.get(curSpellCheckerId);
         }
@@ -187,12 +191,13 @@
             if (!mSpellCheckerMap.containsKey(sciId)) {
                 return;
             }
+            final int uid = Binder.getCallingUid();
             if (mSpellCheckerBindGroups.containsKey(sciId)) {
                 final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId);
                 if (bindGroup != null) {
                     final InternalDeathRecipient recipient =
                             mSpellCheckerBindGroups.get(sciId).addListener(
-                                    tsListener, locale, scListener);
+                                    tsListener, locale, scListener, uid);
                     if (recipient == null) {
                         if (DBG) {
                             Slog.w(TAG, "Didn't create a death recipient.");
@@ -204,14 +209,22 @@
                         bindGroup.removeAll();
                     } else if (bindGroup.mSpellChecker != null) {
                         if (DBG) {
-                            Slog.w(TAG, "Existing bind found. Return a spell checker session now.");
+                            Slog.w(TAG, "Existing bind found. Return a spell checker session now. "
+                                    + "Listeners count = " + bindGroup.mListeners.size());
                         }
                         try {
                             final ISpellCheckerSession session =
                                     bindGroup.mSpellChecker.getISpellCheckerSession(
                                             recipient.mScLocale, recipient.mScListener);
-                            tsListener.onServiceConnected(session);
-                            return;
+                            if (session != null) {
+                                tsListener.onServiceConnected(session);
+                                return;
+                            } else {
+                                if (DBG) {
+                                    Slog.w(TAG, "Existing bind already expired. ");
+                                }
+                                bindGroup.removeAll();
+                            }
                         } catch (RemoteException e) {
                             Slog.e(TAG, "Exception in getting spell checker session: " + e);
                             bindGroup.removeAll();
@@ -221,7 +234,7 @@
             }
             final long ident = Binder.clearCallingIdentity();
             try {
-                startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener);
+                startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener, uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -230,7 +243,11 @@
     }
 
     private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale,
-            ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) {
+            ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
+            int uid) {
+        if (DBG) {
+            Slog.w(TAG, "Start spell checker session inner locked.");
+        }
         final String sciId = info.getId();
         final InternalServiceConnection connection = new InternalServiceConnection(
                 sciId, locale, scListener);
@@ -244,7 +261,7 @@
             return;
         }
         final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
-                connection, tsListener, locale, scListener);
+                connection, tsListener, locale, scListener, uid);
         mSpellCheckerBindGroups.put(sciId, group);
     }
 
@@ -272,19 +289,39 @@
         }
     }
 
-    private void setCurrentSpellChecker(SpellCheckerInfo sci) {
+    @Override
+    public void setCurrentSpellChecker(SpellCheckerInfo sci) {
+        synchronized(mSpellCheckerMap) {
+            if (mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException(
+                        "Requires permission "
+                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
+            }
+            setCurrentSpellCheckerLocked(sci);
+        }
+    }
+
+    private void setCurrentSpellCheckerLocked(SpellCheckerInfo sci) {
         if (DBG) {
             Slog.w(TAG, "setCurrentSpellChecker: " + sci.getId());
         }
-        if (sci == null || mSpellCheckerMap.containsKey(sci.getId())) return;
-        Settings.Secure.putString(mContext.getContentResolver(),
-                Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
+        if (sci == null || !mSpellCheckerMap.containsKey(sci.getId())) return;
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     // SpellCheckerBindGroup contains active text service session listeners.
     // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
     // mSpellCheckerBindGroups
     private class SpellCheckerBindGroup {
+        private final String TAG = SpellCheckerBindGroup.class.getSimpleName();
         private final InternalServiceConnection mInternalConnection;
         private final ArrayList<InternalDeathRecipient> mListeners =
                 new ArrayList<InternalDeathRecipient>();
@@ -293,10 +330,10 @@
 
         public SpellCheckerBindGroup(InternalServiceConnection connection,
                 ITextServicesSessionListener listener, String locale,
-                ISpellCheckerSessionListener scListener) {
+                ISpellCheckerSessionListener scListener, int uid) {
             mInternalConnection = connection;
             mConnected = false;
-            addListener(listener, locale, scListener);
+            addListener(listener, locale, scListener, uid);
         }
 
         public void onServiceConnected(ISpellCheckerService spellChecker) {
@@ -310,7 +347,7 @@
                                 listener.mScLocale, listener.mScListener);
                         listener.mTsListener.onServiceConnected(session);
                     } catch (RemoteException e) {
-                        Slog.e(TAG, "Exception in getting spell checker session: " + e);
+                        Slog.e(TAG, "Exception in getting the spell checker session: " + e);
                         removeAll();
                         return;
                     }
@@ -321,7 +358,7 @@
         }
 
         public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener,
-                String locale, ISpellCheckerSessionListener scListener) {
+                String locale, ISpellCheckerSessionListener scListener, int uid) {
             if (DBG) {
                 Slog.d(TAG, "addListener: " + locale);
             }
@@ -336,10 +373,9 @@
                         }
                     }
                     recipient = new InternalDeathRecipient(
-                            this, tsListener, locale, scListener);
+                            this, tsListener, locale, scListener, uid);
                     scListener.asBinder().linkToDeath(recipient, 0);
-                    mListeners.add(new InternalDeathRecipient(
-                            this, tsListener, locale, scListener));
+                    mListeners.add(recipient);
                 } catch(RemoteException e) {
                     // do nothing
                 }
@@ -350,7 +386,7 @@
 
         public void removeListener(ISpellCheckerSessionListener listener) {
             if (DBG) {
-                Slog.d(TAG, "remove listener");
+                Slog.w(TAG, "remove listener: " + listener.hashCode());
             }
             synchronized(mSpellCheckerMap) {
                 final int size = mListeners.size();
@@ -359,11 +395,17 @@
                 for (int i = 0; i < size; ++i) {
                     final InternalDeathRecipient tempRecipient = mListeners.get(i);
                     if(tempRecipient.hasSpellCheckerListener(listener)) {
+                        if (DBG) {
+                            Slog.w(TAG, "found existing listener.");
+                        }
                         removeList.add(tempRecipient);
                     }
                 }
                 final int removeSize = removeList.size();
                 for (int i = 0; i < removeSize; ++i) {
+                    if (DBG) {
+                        Slog.w(TAG, "Remove " + removeList.get(i));
+                    }
                     mListeners.remove(removeList.get(i));
                 }
                 cleanLocked();
@@ -385,8 +427,10 @@
 
         public void removeAll() {
             Slog.e(TAG, "Remove the spell checker bind unexpectedly.");
-            mListeners.clear();
-            cleanLocked();
+            synchronized(mSpellCheckerMap) {
+                mListeners.clear();
+                cleanLocked();
+            }
         }
     }
 
@@ -426,17 +470,19 @@
         public final ISpellCheckerSessionListener mScListener;
         public final String mScLocale;
         private final SpellCheckerBindGroup mGroup;
+        public final int mUid;
         public InternalDeathRecipient(SpellCheckerBindGroup group,
                 ITextServicesSessionListener tsListener, String scLocale,
-                ISpellCheckerSessionListener scListener) {
+                ISpellCheckerSessionListener scListener, int uid) {
             mTsListener = tsListener;
             mScListener = scListener;
             mScLocale = scLocale;
             mGroup = group;
+            mUid = uid;
         }
 
         public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
-            return mScListener.equals(listener);
+            return listener.asBinder().equals(mScListener.asBinder());
         }
 
         @Override
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 66f88fc..14c6306 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -53,7 +53,7 @@
 import android.app.backup.IBackupManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
-import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -8067,6 +8067,21 @@
 
             if (needSep) pw.println(" ");
             needSep = true;
+            pw.println("  OOM levels:");
+            pw.print("    SYSTEM_ADJ: "); pw.println(SYSTEM_ADJ);
+            pw.print("    CORE_SERVER_ADJ: "); pw.println(CORE_SERVER_ADJ);
+            pw.print("    FOREGROUND_APP_ADJ: "); pw.println(FOREGROUND_APP_ADJ);
+            pw.print("    VISIBLE_APP_ADJ: "); pw.println(VISIBLE_APP_ADJ);
+            pw.print("    PERCEPTIBLE_APP_ADJ: "); pw.println(PERCEPTIBLE_APP_ADJ);
+            pw.print("    HEAVY_WEIGHT_APP_ADJ: "); pw.println(HEAVY_WEIGHT_APP_ADJ);
+            pw.print("    BACKUP_APP_ADJ: "); pw.println(BACKUP_APP_ADJ);
+            pw.print("    SECONDARY_SERVER_ADJ: "); pw.println(SECONDARY_SERVER_ADJ);
+            pw.print("    HOME_APP_ADJ: "); pw.println(HOME_APP_ADJ);
+            pw.print("    HIDDEN_APP_MIN_ADJ: "); pw.println(HIDDEN_APP_MIN_ADJ);
+            pw.print("    EMPTY_APP_ADJ: "); pw.println(EMPTY_APP_ADJ);
+
+            if (needSep) pw.println(" ");
+            needSep = true;
             pw.println("  Process OOM control:");
             dumpProcessOomList(pw, this, procs, "    ",
                     "Proc", "PERS", true);
@@ -8814,7 +8829,8 @@
                 pw.print("    ");
                 pw.print("keeping="); pw.print(r.keeping);
                 pw.print(" hidden="); pw.print(r.hidden);
-                pw.print(" empty="); pw.println(r.empty);
+                pw.print(" empty="); pw.print(r.empty);
+                pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
 
                 if (!r.keeping) {
                     if (r.lastWakeTime != 0) {
@@ -9226,6 +9242,7 @@
         app.foregroundServices = false;
         app.foregroundActivities = false;
         app.hasShownUi = false;
+        app.hasAboveClient = false;
 
         killServicesLocked(app, allowRestart);
 
@@ -10452,6 +10469,9 @@
                 activity.connections.add(c);
             }
             b.client.connections.add(c);
+            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
+                b.client.hasAboveClient = true;
+            }
             clist = mServiceConnections.get(binder);
             if (clist == null) {
                 clist = new ArrayList<ConnectionRecord>();
@@ -10523,6 +10543,9 @@
         }
         if (b.client != skipApp) {
             b.client.connections.remove(c);
+            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
+                b.client.updateHasAboveClientLocked();
+            }
         }
         clist = mServiceConnections.get(binder);
         if (clist != null) {
@@ -12577,9 +12600,9 @@
             // an earlier hidden adjustment that isn't really for us... if
             // so, use the new hidden adjustment.
             if (!recursed && app.hidden) {
-                app.curAdj = hiddenAdj;
+                app.curAdj = app.curRawAdj = hiddenAdj;
             }
-            return app.curAdj;
+            return app.curRawAdj;
         }
 
         if (app.thread == null) {
@@ -12588,28 +12611,47 @@
             return (app.curAdj=EMPTY_APP_ADJ);
         }
 
+        app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
+        app.adjSource = null;
+        app.adjTarget = null;
+        app.empty = false;
+        app.hidden = false;
+
+        final int activitiesSize = app.activities.size();
+
         if (app.maxAdj <= FOREGROUND_APP_ADJ) {
             // The max adjustment doesn't allow this app to be anything
             // below foreground, so it is not worth doing work for it.
             app.adjType = "fixed";
             app.adjSeq = mAdjSeq;
             app.curRawAdj = app.maxAdj;
+            app.foregroundActivities = false;
             app.keeping = true;
             app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
+            // System process can do UI, and when they do we want to have
+            // them trim their memory after the user leaves the UI.  To
+            // facilitate this, here we need to determine whether or not it
+            // is currently showing UI.
+            app.systemNoUi = true;
+            if (app == TOP_APP) {
+                app.systemNoUi = false;
+            } else if (activitiesSize > 0) {
+                for (int j = 0; j < activitiesSize; j++) {
+                    final ActivityRecord r = app.activities.get(j);
+                    if (r.visible) {
+                        app.systemNoUi = false;
+                        break;
+                    }
+                }
+            }
             return (app.curAdj=app.maxAdj);
         }
 
         final boolean hadForegroundActivities = app.foregroundActivities;
 
-        app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
-        app.adjSource = null;
-        app.adjTarget = null;
-        app.keeping = false;
-        app.empty = false;
-        app.hidden = false;
         app.foregroundActivities = false;
-
-        final int activitiesSize = app.activities.size();
+        app.keeping = false;
+        app.systemNoUi = false;
 
         // Determine the importance of the process, starting with most
         // important to least, and assign an appropriate OOM adjustment.
@@ -12784,7 +12826,7 @@
                                 // Binding to ourself is not interesting.
                                 continue;
                             }
-                            if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+                            if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
                                 ProcessRecord client = cr.binding.client;
                                 int clientAdj = adj;
                                 int myHiddenAdj = hiddenAdj;
@@ -12825,15 +12867,32 @@
                                     }
                                 }
                                 if (adj > clientAdj) {
-                                    adj = clientAdj >= VISIBLE_APP_ADJ
-                                            ? clientAdj : VISIBLE_APP_ADJ;
-                                    if (!client.hidden) {
-                                        app.hidden = false;
+                                    // If this process has recently shown UI, and
+                                    // the process that is binding to it is less
+                                    // important than being visible, then we don't
+                                    // care about the binding as much as we care
+                                    // about letting this process get into the LRU
+                                    // list to be killed and restarted if needed for
+                                    // memory.
+                                    if (app.hasShownUi && clientAdj > PERCEPTIBLE_APP_ADJ) {
+                                        adjType = "bound-bg-ui-services";
+                                    } else {
+                                        if ((cr.flags&(Context.BIND_ABOVE_CLIENT
+                                                |Context.BIND_IMPORTANT)) != 0) {
+                                            adj = clientAdj;
+                                        } else if (clientAdj >= VISIBLE_APP_ADJ) {
+                                            adj = clientAdj;
+                                        } else {
+                                            adj = VISIBLE_APP_ADJ;
+                                        }
+                                        if (!client.hidden) {
+                                            app.hidden = false;
+                                        }
+                                        if (client.keeping) {
+                                            app.keeping = true;
+                                        }
+                                        adjType = "service";
                                     }
-                                    if (client.keeping) {
-                                        app.keeping = true;
-                                    }
-                                    adjType = "service";
                                 }
                                 if (adjType != null) {
                                     app.adjType = adjType;
@@ -12848,21 +12907,22 @@
                                     }
                                 }
                             }
-                            ActivityRecord a = cr.activity;
-                            //if (a != null) {
-                            //    Slog.i(TAG, "Connection to " + a ": state=" + a.state);
-                            //}
-                            if (a != null && adj > FOREGROUND_APP_ADJ &&
-                                    (a.state == ActivityState.RESUMED
-                                     || a.state == ActivityState.PAUSING)) {
-                                adj = FOREGROUND_APP_ADJ;
-                                schedGroup = Process.THREAD_GROUP_DEFAULT;
-                                app.hidden = false;
-                                app.adjType = "service";
-                                app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                        .REASON_SERVICE_IN_USE;
-                                app.adjSource = a;
-                                app.adjTarget = s.name;
+                            if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
+                                ActivityRecord a = cr.activity;
+                                if (a != null && adj > FOREGROUND_APP_ADJ &&
+                                        (a.visible || a.state == ActivityState.RESUMED
+                                         || a.state == ActivityState.PAUSING)) {
+                                    adj = FOREGROUND_APP_ADJ;
+                                    if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                    }
+                                    app.hidden = false;
+                                    app.adjType = "service";
+                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                            .REASON_SERVICE_IN_USE;
+                                    app.adjSource = a;
+                                    app.adjTarget = s.name;
+                                }
                             }
                         }
                     }
@@ -12906,15 +12966,19 @@
                         int clientAdj = computeOomAdjLocked(
                             client, myHiddenAdj, TOP_APP, true);
                         if (adj > clientAdj) {
-                            adj = clientAdj > FOREGROUND_APP_ADJ
-                                    ? clientAdj : FOREGROUND_APP_ADJ;
+                            if (app.hasShownUi && clientAdj > PERCEPTIBLE_APP_ADJ) {
+                                app.adjType = "bg-ui-provider";
+                            } else {
+                                adj = clientAdj > FOREGROUND_APP_ADJ
+                                        ? clientAdj : FOREGROUND_APP_ADJ;
+                                app.adjType = "provider";
+                            }
                             if (!client.hidden) {
                                 app.hidden = false;
                             }
                             if (client.keeping) {
                                 app.keeping = true;
                             }
-                            app.adjType = "provider";
                             app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                     .REASON_PROVIDER_IN_USE;
                             app.adjSource = client;
@@ -12955,6 +13019,25 @@
             app.keeping = true;
         }
 
+        if (app.hasAboveClient) {
+            // If this process has bound to any services with BIND_ABOVE_CLIENT,
+            // then we need to drop its adjustment to be lower than the service's
+            // in order to honor the request.  We want to drop it by one adjustment
+            // level...  but there is special meaning applied to various levels so
+            // we will skip some of them.
+            if (adj < FOREGROUND_APP_ADJ) {
+                // System process will not get dropped, ever
+            } else if (adj < VISIBLE_APP_ADJ) {
+                adj = VISIBLE_APP_ADJ;
+            } else if (adj < PERCEPTIBLE_APP_ADJ) {
+                adj = PERCEPTIBLE_APP_ADJ;
+            } else if (adj < HIDDEN_APP_MIN_ADJ) {
+                adj = HIDDEN_APP_MIN_ADJ;
+            } else if (adj < EMPTY_APP_ADJ) {
+                adj++;
+            }
+        }
+
         app.curAdj = adj;
         app.curSchedGroup = schedGroup;
 
@@ -12963,7 +13046,7 @@
                     app.foregroundActivities).sendToTarget();
         }
 
-        return adj;
+        return app.curRawAdj;
     }
 
     /**
@@ -13204,7 +13287,7 @@
 
         final boolean wasKeeping = app.keeping;
 
-        int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
+        computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
 
         if (app.curRawAdj != app.setRawAdj) {
             if (app.curRawAdj > FOREGROUND_APP_ADJ
@@ -13233,14 +13316,14 @@
 
             app.setRawAdj = app.curRawAdj;
         }
-        if (adj != app.setAdj) {
-            if (Process.setOomAdj(app.pid, adj)) {
+        if (app.curAdj != app.setAdj) {
+            if (Process.setOomAdj(app.pid, app.curAdj)) {
                 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
                     TAG, "Set app " + app.processName +
-                    " oom adj to " + adj + " because " + app.adjType);
-                app.setAdj = adj;
+                    " oom adj to " + app.curAdj + " because " + app.adjType);
+                app.setAdj = app.curAdj;
             } else {
-                Slog.w(TAG, "Failed setting oom adj of " + app + " to " + adj);
+                Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
             }
         }
         if (app.setSchedGroup != app.curSchedGroup) {
@@ -13377,7 +13460,7 @@
             final int N = mLruProcesses.size();
             factor = numBg/3;
             step = 0;
-            int curLevel = ComponentCallbacks.TRIM_MEMORY_COMPLETE;
+            int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             for (i=0; i<N; i++) {
                 ProcessRecord app = mLruProcesses.get(i);
                 if (app.curAdj >= HIDDEN_APP_MIN_ADJ && !app.killedBackground) {
@@ -13386,7 +13469,7 @@
                             app.thread.scheduleTrimMemory(curLevel);
                         } catch (RemoteException e) {
                         }
-                        if (curLevel >= ComponentCallbacks.TRIM_MEMORY_COMPLETE) {
+                        if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
                             // For these apps we will also finish their activities
                             // to help them free memory.
                             mMainStack.destroyActivitiesLocked(app, false);
@@ -13396,23 +13479,36 @@
                     step++;
                     if (step >= factor) {
                         switch (curLevel) {
-                            case ComponentCallbacks.TRIM_MEMORY_COMPLETE:
-                                curLevel = ComponentCallbacks.TRIM_MEMORY_MODERATE;
+                            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+                                curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
                                 break;
-                            case ComponentCallbacks.TRIM_MEMORY_MODERATE:
-                                curLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
+                            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+                                curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
                                 break;
                         }
                     }
                 } else if (app.curAdj == HEAVY_WEIGHT_APP_ADJ) {
-                    if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_BACKGROUND
+                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
                             && app.thread != null) {
                         try {
-                            app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_BACKGROUND);
+                            app.thread.scheduleTrimMemory(
+                                    ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                         } catch (RemoteException e) {
                         }
                     }
-                    app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
+                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+                } else if ((app.curAdj > VISIBLE_APP_ADJ || app.systemNoUi)
+                        && app.pendingUiClean) {
+                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
+                            && app.thread != null) {
+                        try {
+                            app.thread.scheduleTrimMemory(
+                                    ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+                    app.pendingUiClean = false;
                 } else {
                     app.trimMemoryLevel = 0;
                 }
@@ -13421,7 +13517,21 @@
             final int N = mLruProcesses.size();
             for (i=0; i<N; i++) {
                 ProcessRecord app = mLruProcesses.get(i);
-                app.trimMemoryLevel = 0;
+                if ((app.curAdj > VISIBLE_APP_ADJ || app.systemNoUi)
+                        && app.pendingUiClean) {
+                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
+                            && app.thread != null) {
+                        try {
+                            app.thread.scheduleTrimMemory(
+                                    ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+                    app.pendingUiClean = false;
+                } else {
+                    app.trimMemoryLevel = 0;
+                }
             }
         }
 
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index cc58eaf..33b21ab 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -560,6 +560,7 @@
             showAskCompatModeDialogLocked(r);
             r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
             app.hasShownUi = true;
+            app.pendingUiClean = true;
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
                     System.identityHashCode(r),
                     r.info, r.compat, r.icicle, results, newIntents, !andResume,
diff --git a/services/java/com/android/server/am/AppBindRecord.java b/services/java/com/android/server/am/AppBindRecord.java
index 9c57360..f1c54fa 100644
--- a/services/java/com/android/server/am/AppBindRecord.java
+++ b/services/java/com/android/server/am/AppBindRecord.java
@@ -26,7 +26,7 @@
 class AppBindRecord {
     final ServiceRecord service;    // The running service.
     final IntentBindRecord intent;  // The intent we are bound to.
-    final ProcessRecord client; // Who has started/bound the service.
+    final ProcessRecord client;     // Who has started/bound the service.
 
     final HashSet<ConnectionRecord> connections = new HashSet<ConnectionRecord>();
                                     // All ConnectionRecord for this client.
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 5b59363..a896ce4 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -23,6 +23,7 @@
 import android.app.IApplicationThread;
 import android.app.IInstrumentationWatcher;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.res.CompatibilityInfo;
 import android.os.Bundle;
@@ -66,7 +67,10 @@
     boolean setIsForeground;    // Running foreground UI when last set?
     boolean foregroundServices; // Running any services that are foreground?
     boolean foregroundActivities; // Running any activities that are foreground?
+    boolean systemNoUi;         // This is a system process, but not currently showing UI.
     boolean hasShownUi;         // Has UI been shown in this process since it was started?
+    boolean pendingUiClean;     // Want to clean up resources from showing UI?
+    boolean hasAboveClient;     // Bound using BIND_ABOVE_CLIENT, so want to be lower
     boolean bad;                // True if disabled in the bad process list
     boolean killedBackground;   // True when proc has been killed due to too many bg
     String waitingToKill;       // Process is waiting to be killed when in the bg; reason
@@ -185,8 +189,11 @@
                 pw.print(" set="); pw.println(setAdj);
         pw.print(prefix); pw.print("curSchedGroup="); pw.print(curSchedGroup);
                 pw.print(" setSchedGroup="); pw.print(setSchedGroup);
+                pw.print(" systemNoUi="); pw.print(systemNoUi);
                 pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
-                pw.print(" hasShownUi="); pw.println(hasShownUi);
+        pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);
+                pw.print(" pendingUiClean="); pw.print(pendingUiClean);
+                pw.print(" hasAboveClient="); pw.println(hasAboveClient);
         pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);
                 pw.print(" foregroundServices="); pw.print(foregroundServices);
                 pw.print(" forcingToForeground="); pw.println(forcingToForeground);
@@ -307,6 +314,18 @@
         deathRecipient = null;
     }
 
+    void updateHasAboveClientLocked() {
+        hasAboveClient = false;
+        if (connections.size() > 0) {
+            for (ConnectionRecord cr : connections) {
+                if ((cr.flags&Context.BIND_ABOVE_CLIENT) != 0) {
+                    hasAboveClient = true;
+                    break;
+                }
+            }
+        }
+    }
+
     public String toShortString() {
         if (shortStringName != null) {
             return shortStringName;
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index e75a079..da5f488 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -48,6 +48,8 @@
     StatusBarManager mStatusBarManager;
     NotificationManager mNotificationManager;
     Handler mHandler = new Handler();
+    int mUiVisibility = 0;
+    View mListView;
 
     View.OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener
             = new View.OnSystemUiVisibilityChangeListener() {
@@ -69,32 +71,52 @@
         return mTests;
     }
 
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        mListView = findViewById(android.R.id.list);
+        mListView.setOnSystemUiVisibilityChangeListener(mOnSystemUiVisibilityChangeListener);
+    }
+
     private Test[] mTests = new Test[] {
+        new Test("toggle LOW_PROFILE (lights out)") {
+            public void run() {
+                if (0 != (mUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE)) {
+                    mUiVisibility &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
+                } else {
+                    mUiVisibility |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
+                }
+                mListView.setSystemUiVisibility(mUiVisibility);
+            }
+        },
+        new Test("toggle HIDE_NAVIGATION") {
+            public void run() {
+                if (0 != (mUiVisibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) {
+                    mUiVisibility &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+                } else {
+                    mUiVisibility |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+                }
+                mListView.setSystemUiVisibility(mUiVisibility);
+
+            }
+        },
+        new Test("clear SYSTEM_UI_FLAGs") {
+            public void run() {
+                mUiVisibility = 0;
+                mListView.setSystemUiVisibility(mUiVisibility);
+            }
+        },
+//        new Test("no setSystemUiVisibility") {
+//            public void run() {
+//                View v = findViewById(android.R.id.list);
+//                v.setOnSystemUiVisibilityChangeListener(null);
+//                v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+//            }
+//        },
         new Test("DISABLE_NAVIGATION") {
             public void run() {
-                View v = findViewById(android.R.id.list);
-                v.setSystemUiVisibility(View.STATUS_BAR_DISABLE_NAVIGATION);
-            }
-        },
-        new Test("STATUS_BAR_HIDDEN") {
-            public void run() {
-                View v = findViewById(android.R.id.list);
-                v.setOnSystemUiVisibilityChangeListener(mOnSystemUiVisibilityChangeListener);
-                v.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
-            }
-        },
-        new Test("STATUS_BAR_VISIBLE") {
-            public void run() {
-                View v = findViewById(android.R.id.list);
-                v.setOnSystemUiVisibilityChangeListener(mOnSystemUiVisibilityChangeListener);
-                v.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
-            }
-        },
-        new Test("no setSystemUiVisibility") {
-            public void run() {
-                View v = findViewById(android.R.id.list);
-                v.setOnSystemUiVisibilityChangeListener(null);
-                v.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
+                mListView.setSystemUiVisibility(View.STATUS_BAR_DISABLE_NAVIGATION);
             }
         },
         new Test("Double Remove") {