Merge "Print timestamp (instead of age) in Location#toString()" into jb-mr1-dev
diff --git a/api/17.txt b/api/17.txt
index c43802f..d002449 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -24500,7 +24500,6 @@
     field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
     field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
     field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
-    field public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = 131072; // 0x20000
     field public static final android.util.Property TRANSLATION_X;
     field public static final android.util.Property TRANSLATION_Y;
     field protected static final java.lang.String VIEW_LOG_TAG = "View";
diff --git a/api/current.txt b/api/current.txt
index b489dfd..e1d07e2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5838,7 +5838,7 @@
     field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
     field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
     field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
-    field public static final java.lang.String EXTRA_ORIGINATING_URL = "android.intent.extra.ORIGINATING_URL";
+    field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
     field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
@@ -9981,6 +9981,15 @@
 package android.hardware.display {
 
   public final class DisplayManager {
+    method public android.view.Display getDisplay(int, android.content.Context);
+    method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
+    method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
+  }
+
+  public static abstract interface DisplayManager.DisplayListener {
+    method public abstract void onDisplayAdded(int);
+    method public abstract void onDisplayChanged(int);
+    method public abstract void onDisplayRemoved(int);
   }
 
 }
@@ -13217,6 +13226,7 @@
     field public java.lang.String capabilities;
     field public int frequency;
     field public int level;
+    field public long timestamp;
   }
 
   public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -15515,6 +15525,7 @@
     field public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6; // 0x6
     field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
     field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
+    field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
     field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2
     field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3
     field public static final int BATTERY_STATUS_FULL = 5; // 0x5
@@ -22494,6 +22505,17 @@
     method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt, android.text.TextPaint);
   }
 
+  public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
+    ctor public LocaleSpan(java.util.Locale);
+    ctor public LocaleSpan(android.os.Parcel);
+    method public int describeContents();
+    method public java.util.Locale getLocale();
+    method public int getSpanTypeId();
+    method public void updateDrawState(android.text.TextPaint);
+    method public void updateMeasureState(android.text.TextPaint);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
   public class MaskFilterSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
     ctor public MaskFilterSpan(android.graphics.MaskFilter);
     method public android.graphics.MaskFilter getMaskFilter();
@@ -24579,6 +24601,7 @@
     method public final android.content.Context getContext();
     method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
     method public static int getDefaultSize(int, int);
+    method public android.view.Display getDisplay();
     method public final int[] getDrawableState();
     method public android.graphics.Bitmap getDrawingCache();
     method public android.graphics.Bitmap getDrawingCache(boolean);
@@ -25029,16 +25052,15 @@
     field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
     field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
     field public static final int TEXT_ALIGNMENT_CENTER = 4; // 0x4
-    field protected static int TEXT_ALIGNMENT_DEFAULT;
+    field public static int TEXT_ALIGNMENT_DEFAULT;
     field public static final int TEXT_ALIGNMENT_GRAVITY = 1; // 0x1
     field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
-    field public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = 131072; // 0x20000
     field public static final int TEXT_ALIGNMENT_TEXT_END = 3; // 0x3
     field public static final int TEXT_ALIGNMENT_TEXT_START = 2; // 0x2
     field public static final int TEXT_ALIGNMENT_VIEW_END = 6; // 0x6
     field public static final int TEXT_ALIGNMENT_VIEW_START = 5; // 0x5
     field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
-    field protected static int TEXT_DIRECTION_DEFAULT;
+    field public static int TEXT_DIRECTION_DEFAULT;
     field public static final int TEXT_DIRECTION_FIRST_STRONG = 1; // 0x1
     field public static final int TEXT_DIRECTION_INHERIT = 0; // 0x0
     field public static final int TEXT_DIRECTION_LOCALE = 5; // 0x5
@@ -26927,6 +26949,7 @@
     method public synchronized boolean getUseWideViewPort();
     method public deprecated synchronized int getUserAgent();
     method public synchronized java.lang.String getUserAgentString();
+    method public static java.lang.String getDefaultUserAgent(android.content.Context);
     method public void setAllowContentAccess(boolean);
     method public void setAllowFileAccess(boolean);
     method public abstract void setAllowFileAccessFromFileURLs(boolean);
@@ -29294,6 +29317,7 @@
     method public static int getTextColor(android.content.Context, android.content.res.TypedArray, int);
     method public final android.content.res.ColorStateList getTextColors();
     method public static android.content.res.ColorStateList getTextColors(android.content.Context, android.content.res.TypedArray);
+    method public java.util.Locale getTextLocale();
     method public float getTextScaleX();
     method public float getTextSize();
     method public int getTotalPaddingBottom();
@@ -29396,6 +29420,7 @@
     method public void setTextIsSelectable(boolean);
     method public final void setTextKeepState(java.lang.CharSequence);
     method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
+    method public void setTextLocale(java.util.Locale);
     method public void setTextScaleX(float);
     method public void setTextSize(float);
     method public void setTextSize(int, float);
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 0a7cb2d8..c16e6fb 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -432,7 +432,7 @@
     return 0;
 }
 
-int get_size(const char *pkgname, const char *apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath,
              const char *fwdlock_apkpath, const char *asecpath,
              int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
              int64_t* _asecsize)
@@ -479,7 +479,7 @@
         }
     }
 
-    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
+    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
         goto done;
     }
 
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index b8d0bd7..7108d68 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -85,8 +85,9 @@
     int64_t asecsize = 0;
     int res = 0;
 
-        /* pkgdir, apkpath */
-    res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
+        /* pkgdir, persona, apkpath */
+    res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4],
+            &codesize, &datasize, &cachesize, &asecsize);
 
     /*
      * Each int64_t can take up 22 characters printed out. Make sure it
@@ -150,7 +151,7 @@
     { "freecache",            1, do_free_cache },
     { "rmcache",              1, do_rm_cache },
     { "protect",              2, do_protect },
-    { "getsize",              4, do_get_size },
+    { "getsize",              5, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
     { "linklib",              2, do_linklib },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index f5485d2..3201427 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -199,7 +199,7 @@
 int move_dex(const char *src, const char *dst);
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
+int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath,
              const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
              int64_t *asecsize);
 int free_cache(int64_t free_size);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index eb1f9a2..b34fd05 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -36,6 +36,7 @@
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
@@ -787,6 +788,8 @@
         String macAlgo = null;
         byte[] macKey = null;
         byte[] tag = null;
+        String originatingUriString = null;
+        String referrer = null;
 
         while ((opt=nextOption()) != null) {
             if (opt.equals("-l")) {
@@ -850,6 +853,20 @@
                     showUsage();
                     return;
                 }
+            } else if (opt.equals("--originating-uri")) {
+                originatingUriString = nextOptionData();
+                if (originatingUriString == null) {
+                    System.err.println("Error: must supply argument for --originating-uri");
+                    showUsage();
+                    return;
+                }
+            } else if (opt.equals("--referrer")) {
+                referrer = nextOptionData();
+                if (referrer == null) {
+                    System.err.println("Error: must supply argument for --referrer");
+                    showUsage();
+                    return;
+                }
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 showUsage();
@@ -897,6 +914,20 @@
 
         final Uri apkURI;
         final Uri verificationURI;
+        final Uri originatingURI;
+        final Uri referrerURI;
+
+        if (originatingUriString != null) {
+            originatingURI = Uri.parse(originatingUriString);
+        } else {
+            originatingURI = null;
+        }
+
+        if (referrer != null) {
+            referrerURI = Uri.parse(referrer);
+        } else {
+            referrerURI = null;
+        }
 
         // Populate apkURI, must be present
         final String apkFilePath = nextArg();
@@ -920,8 +951,11 @@
 
         PackageInstallObserver obs = new PackageInstallObserver();
         try {
-            mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
-                    verificationURI, null, encryptionParams);
+            VerificationParams verificationParams = new VerificationParams(verificationURI,
+                    originatingURI, referrerURI, null);
+
+            mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
+                    installerPackageName, verificationParams, encryptionParams);
 
             synchronized (obs) {
                 while (!obs.finished) {
@@ -1441,7 +1475,8 @@
         System.err.println("       pm list libraries");
         System.err.println("       pm path PACKAGE");
         System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]");
-        System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH");
+        System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]");
+        System.err.println("                  [--originating-uri <URI>] [--referrer <URI>] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
         System.err.println("       pm clear PACKAGE");
         System.err.println("       pm enable PACKAGE_OR_COMPONENT");
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index deef2a3..ec3ec3e 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -37,7 +37,7 @@
     public String longHelp() {
         return shortHelp() + "\n"
                 + "\n"
-                + "usage: svc power stayon [true|false|usb|ac]\n"
+                + "usage: svc power stayon [true|false|usb|ac|wireless]\n"
                 + "         Set the 'keep awake while plugged in' setting.\n";
     }
 
@@ -48,7 +48,8 @@
                     int val;
                     if ("true".equals(args[2])) {
                         val = BatteryManager.BATTERY_PLUGGED_AC |
-                                BatteryManager.BATTERY_PLUGGED_USB;
+                                BatteryManager.BATTERY_PLUGGED_USB |
+                                BatteryManager.BATTERY_PLUGGED_WIRELESS;
                     }
                     else if ("false".equals(args[2])) {
                         val = 0;
@@ -56,8 +57,9 @@
                         val = BatteryManager.BATTERY_PLUGGED_USB;
                     } else if ("ac".equals(args[2])) {
                         val = BatteryManager.BATTERY_PLUGGED_AC;
-                    }
-                    else {
+                    } else if ("wireless".equals(args[2])) {
+                        val = BatteryManager.BATTERY_PLUGGED_WIRELESS;
+                    } else {
                         break fail;
                     }
                     IPowerManager pm
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 809acac..395a79c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -74,7 +74,7 @@
 import android.view.ViewManager;
 import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
 
@@ -4733,6 +4733,29 @@
             mLoaderManager.dump(prefix + "  ", fd, writer, args);
         }
         mFragments.dump(prefix, fd, writer, args);
+        writer.print(prefix); writer.println("View Hierarchy:");
+        dumpViewHierarchy(prefix + "  ", writer, getWindow().getDecorView());
+    }
+
+    private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
+        writer.print(prefix);
+        if (view == null) {
+            writer.println("null");
+            return;
+        }
+        writer.println(view.toString());
+        if (!(view instanceof ViewGroup)) {
+            return;
+        }
+        ViewGroup grp = (ViewGroup)view;
+        final int N = grp.getChildCount();
+        if (N <= 0) {
+            return;
+        }
+        prefix = prefix + "  ";
+        for (int i=0; i<N; i++) {
+            dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
+        }
     }
 
     /**
@@ -4995,7 +5018,9 @@
         mEmbeddedID = id;
         mLastNonConfigurationInstances = lastNonConfigurationInstances;
 
-        mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
+        mWindow.setWindowManager(
+                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
+                mToken, mComponent.flattenToString(),
                 (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
         if (mParent != null) {
             mWindow.setContainer(mParent.getWindow());
@@ -5042,7 +5067,7 @@
         if (mStopped) {
             mStopped = false;
             if (mToken != null && mParent == null) {
-                WindowManagerImpl.getDefault().setStoppedState(mToken, false);
+                WindowManagerGlobal.getInstance().setStoppedState(mToken, false);
             }
 
             synchronized (mManagedCursors) {
@@ -5142,7 +5167,7 @@
             }
 
             if (mToken != null && mParent == null) {
-                WindowManagerImpl.getDefault().setStoppedState(mToken, true);
+                WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
             }
             
             mFragments.dispatchStop();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2c6d5d9..e644db4 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -30,6 +30,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.hardware.display.DisplayManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
@@ -366,7 +367,7 @@
      * (which tends to consume a lot more RAM).
      * @hide
      */
-    static public boolean isHighEndGfx(Display display) {
+    static public boolean isHighEndGfx() {
         MemInfoReader reader = new MemInfoReader();
         reader.readMemInfo();
         if (reader.getTotalSize() >= (512*1024*1024)) {
@@ -374,6 +375,8 @@
             // we can afford the overhead of graphics acceleration.
             return true;
         }
+
+        Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
         Point p = new Point();
         display.getRealSize(p);
         int pixels = p.x * p.y;
@@ -1375,6 +1378,13 @@
         public static final int FLAG_PERSISTENT = 1<<1;
 
         /**
+         * Constant for {@link #flags}: this process is associated with a
+         * persistent system app.
+         * @hide
+         */
+        public static final int FLAG_HAS_ACTIVITIES = 1<<2;
+
+        /**
          * Flags of information.  May be any of
          * {@link #FLAG_CANT_SAVE_STATE}.
          * @hide
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7eb86f4..4740e53c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -42,6 +42,7 @@
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.hardware.display.DisplayManager;
 import android.net.IConnectivityManager;
 import android.net.Proxy;
 import android.net.ProxyProperties;
@@ -79,8 +80,9 @@
 import android.view.ViewRootImpl;
 import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.renderscript.RenderScript;
+import android.security.AndroidKeyStoreProvider;
 
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
@@ -95,6 +97,7 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
+import java.security.Security;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -1055,7 +1058,7 @@
         @Override
         public void dumpGfxInfo(FileDescriptor fd, String[] args) {
             dumpGraphicsInfo(fd);
-            WindowManagerImpl.getDefault().dumpGfxInfo(fd);
+            WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
         }
 
         @Override
@@ -1553,13 +1556,23 @@
         if (dm != null && !forceUpdate) {
             return dm;
         }
+
+        DisplayManager displayManager = DisplayManager.getInstance();
+        if (displayManager == null) {
+            // may be null early in system startup
+            dm = new DisplayMetrics();
+            dm.setToDefaults();
+            return dm;
+        }
+
         if (dm == null) {
             dm = new DisplayMetrics();
             mDisplayMetrics.put(ci, dm);
         }
+
         CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
         cih.set(ci);
-        Display d = WindowManagerImpl.getDefault().makeCompatible(cih).getDefaultDisplay();
+        Display d = displayManager.getCompatibleDisplay(Display.DEFAULT_DISPLAY, cih);
         d.getMetrics(dm);
         //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
         //        + metrics.heightPixels + " den=" + metrics.density
@@ -2631,7 +2644,7 @@
             r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow);
             IBinder wtoken = r.mPendingRemoveWindow.getWindowToken();
             if (wtoken != null) {
-                WindowManagerImpl.getDefault().closeAll(wtoken,
+                WindowManagerGlobal.getInstance().closeAll(wtoken,
                         r.activity.getClass().getName(), "Activity");
             }
         }
@@ -3166,7 +3179,7 @@
             apk.mCompatibilityInfo.set(data.info);
         }
         handleConfigurationChanged(mConfiguration, data.info);
-        WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration);
+        WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
     }
 
     private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
@@ -3355,7 +3368,7 @@
                     }
                 }
                 if (wtoken != null && r.mPendingRemoveWindow == null) {
-                    WindowManagerImpl.getDefault().closeAll(wtoken,
+                    WindowManagerGlobal.getInstance().closeAll(wtoken,
                             r.activity.getClass().getName(), "Activity");
                 }
                 r.activity.mDecor = null;
@@ -3367,7 +3380,7 @@
                 // by the app will leak.  Well we try to warning them a lot
                 // about leaking windows, because that is a bug, so if they are
                 // using this recreate facility then they get to live with leaks.
-                WindowManagerImpl.getDefault().closeAll(token,
+                WindowManagerGlobal.getInstance().closeAll(token,
                         r.activity.getClass().getName(), "Activity");
             }
 
@@ -3795,7 +3808,7 @@
         }
         
         // Cleanup hardware accelerated stuff
-        WindowManagerImpl.getDefault().trimLocalMemory();
+        WindowManagerGlobal.getInstance().trimLocalMemory();
 
         freeTextLayoutCachesIfNeeded(configDiff);
 
@@ -3935,7 +3948,7 @@
     final void handleTrimMemory(int level) {
         if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
 
-        final WindowManagerImpl windowManager = WindowManagerImpl.getDefault();
+        final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
         windowManager.startTrimMemory(level);
 
         ArrayList<ComponentCallbacks2> callbacks;
@@ -3948,7 +3961,7 @@
             callbacks.get(i).onTrimMemory(level);
         }
 
-        windowManager.endTrimMemory();        
+        windowManager.endTrimMemory();
     }
 
     private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
@@ -4001,8 +4014,7 @@
             // Persistent processes on low-memory devices do not get to
             // use hardware accelerated drawing, since this can add too much
             // overhead to the process.
-            final Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
-            if (!ActivityManager.isHighEndGfx(display)) {
+            if (!ActivityManager.isHighEndGfx()) {
                 HardwareRenderer.disable(false);
             }
         }
@@ -4055,13 +4067,14 @@
 
         final ContextImpl appContext = new ContextImpl();
         appContext.init(data.info, null, this);
-        final File cacheDir = appContext.getCacheDir();
+        if (!Process.isIsolated()) {
+            final File cacheDir = appContext.getCacheDir();
 
-        // Provide a usable directory for temporary files
-        System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
+            // Provide a usable directory for temporary files
+            System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
 
-        setupGraphicsSupport(data.info, cacheDir);
-
+            setupGraphicsSupport(data.info, cacheDir);
+        }
         /**
          * For system applications on userdebug/eng builds, log stack
          * traces of disk and network access to dropbox for analysis.
@@ -4799,6 +4812,8 @@
         // StrictMode) on debug builds, but using DropBox, not logs.
         CloseGuard.setEnabled(false);
 
+        Security.addProvider(new AndroidKeyStoreProvider());
+
         Process.setArgV0("<pre-initialized>");
 
         Looper.prepareMainLooper();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 115c867..86ee8a0 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -43,6 +43,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.ManifestDigest;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -984,6 +985,18 @@
     }
 
     @Override
+	  public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        try {
+            mPM.installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+                    installerPackageName, verificationParams, encryptionParams);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
     public void verifyPendingInstall(int id, int response) {
         try {
             mPM.verifyPendingInstall(id, response);
@@ -1066,10 +1079,10 @@
     }
 
     @Override
-    public void getPackageSizeInfo(String packageName,
-                                   IPackageStatsObserver observer) {
+    public void getPackageSizeInfo(String packageName, int userHandle,
+            IPackageStatsObserver observer) {
         try {
-            mPM.getPackageSizeInfo(packageName, observer);
+            mPM.getPackageSizeInfo(packageName, userHandle, observer);
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1106,7 +1119,17 @@
     public void addPreferredActivity(IntentFilter filter,
                                      int match, ComponentName[] set, ComponentName activity) {
         try {
-            mPM.addPreferredActivity(filter, match, set, activity);
+            mPM.addPreferredActivity(filter, match, set, activity, UserHandle.myUserId());
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void addPreferredActivity(IntentFilter filter, int match,
+            ComponentName[] set, ComponentName activity, int userId) {
+        try {
+            mPM.addPreferredActivity(filter, match, set, activity, userId);
         } catch (RemoteException e) {
             // Should never happen!
         }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 08947a4..0543f05 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -95,7 +95,9 @@
 import android.content.ClipboardManager;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
+import android.view.CompatibilityInfoHolder;
 import android.view.ContextThemeWrapper;
+import android.view.Display;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
@@ -499,8 +501,8 @@
 
         registerService(WINDOW_SERVICE, new ServiceFetcher() {
                 public Object getService(ContextImpl ctx) {
-                    return WindowManagerImpl.getDefault().makeCompatible(
-                            ctx.mPackageInfo.mCompatibilityInfo);
+                    return new WindowManagerImpl(ctx.getOuterContext(),
+                            Display.DEFAULT_DISPLAY);
                 }});
 
         registerService(USER_SERVICE, new ServiceFetcher() {
@@ -1609,6 +1611,11 @@
         return mRestricted;
     }
 
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        return mPackageInfo.mCompatibilityInfo;
+    }
+
     private File getDataDirFile() {
         if (mPackageInfo != null) {
             return mPackageInfo.getDataDirFile();
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index c1e11bb..52a6557 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -428,92 +428,26 @@
         }
     };
 
-    private void logViewHierarchy(String prefix, View view) {
-        StringBuilder builder = new StringBuilder(128);
-        builder.append(prefix);
-        DebugUtils.buildShortClassTag(view, builder);
-        int id = view.getId();
-        if (id != -1) {
-            builder.append(" #");
-            builder.append(Integer.toHexString(id));
-            if (id != 0 && id != -1) {
-                try {
-                    String pkgname;
-                    switch (id&0xff000000) {
-                        case 0x7f000000:
-                            pkgname="app";
-                            break;
-                        case 0x01000000:
-                            pkgname="android";
-                            break;
-                        default:
-                            pkgname = view.getResources().getResourcePackageName(id);
-                            break;
-                    }
-                    String typename = view.getResources().getResourceTypeName(id);
-                    String entryname = view.getResources().getResourceEntryName(id);
-                    builder.append(" (");
-                    builder.append(pkgname);
-                    builder.append(":");
-                    builder.append(typename);
-                    builder.append("/");
-                    builder.append(entryname);
-                    builder.append(")");
-                } catch (Resources.NotFoundException e) {
-                }
-            }
-        }
-        Object tag = view.getTag();
-        if (tag != null) {
-            builder.append(" ");
-            builder.append(tag);
-        }
-        builder.append("}");
-        Log.e(TAG, builder.toString());
-
-        if (!(view instanceof ViewGroup)) {
-            return;
-        }
-        ViewGroup grp = (ViewGroup)view;
-        final int N = grp.getChildCount();
-        if (N <= 0) {
-            return;
-        }
-        prefix = prefix + "  ";
-        for (int i=0; i<N; i++) {
-            logViewHierarchy(prefix, grp.getChildAt(i));
-        }
-    }
-
-    private void throwNoViewFound(Fragment f) {
-        String msg = "No view found for id 0x"
-                + Integer.toHexString(f.mContainerId) + " ("
-                + f.getResources().getResourceName(f.mContainerId)
-                + ") for fragment " + f;
-        Log.e(TAG, msg);
-        Log.e(TAG, "Activity state:");
-        if (f.getActivity() != null) {
+    private void throwException(RuntimeException ex) {
+        Log.e(TAG, ex.getMessage());
+        LogWriter logw = new LogWriter(Log.ERROR, TAG);
+        PrintWriter pw = new PrintWriter(logw);
+        if (mActivity != null) {
+            Log.e(TAG, "Activity state:");
             try {
-                LogWriter logw = new LogWriter(Log.ERROR, TAG);
-                PrintWriter pw = new PrintWriter(logw);
-                f.getActivity().dump("  ", null, pw, new String[] { });
+                mActivity.dump("  ", null, pw, new String[] { });
             } catch (Exception e) {
                 Log.e(TAG, "Failed dumping state", e);
             }
         } else {
-            Log.e(TAG, "  NULL ACTIVITY!");
-        }
-        Log.e(TAG, "View hierarchy:");
-        if (f.getActivity() != null) {
+            Log.e(TAG, "Fragment manager state:");
             try {
-                logViewHierarchy("  ", f.getActivity().getWindow().getDecorView());
+                dump("  ", null, pw, new String[] { });
             } catch (Exception e) {
-                Log.e(TAG, "Failed dumping view hierarchy", e);
+                Log.e(TAG, "Failed dumping state", e);
             }
-        } else {
-            Log.e(TAG, "  NULL ACTIVITY!");
         }
-        throw new IllegalArgumentException(msg);
+        throw ex;
     }
 
     @Override
@@ -608,8 +542,8 @@
     @Override
     public void putFragment(Bundle bundle, String key, Fragment fragment) {
         if (fragment.mIndex < 0) {
-            throw new IllegalStateException("Fragment " + fragment
-                    + " is not currently in the FragmentManager");
+            throwException(new IllegalStateException("Fragment " + fragment
+                    + " is not currently in the FragmentManager"));
         }
         bundle.putInt(key, fragment.mIndex);
     }
@@ -621,13 +555,13 @@
             return null;
         }
         if (index >= mActive.size()) {
-            throw new IllegalStateException("Fragement no longer exists for key "
-                    + key + ": index " + index);
+            throwException(new IllegalStateException("Fragement no longer exists for key "
+                    + key + ": index " + index));
         }
         Fragment f = mActive.get(index);
         if (f == null) {
-            throw new IllegalStateException("Fragement no longer exists for key "
-                    + key + ": index " + index);
+            throwException(new IllegalStateException("Fragement no longer exists for key "
+                    + key + ": index " + index));
         }
         return f;
     }
@@ -635,8 +569,8 @@
     @Override
     public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) {
         if (fragment.mIndex < 0) {
-            throw new IllegalStateException("Fragment " + fragment
-                    + " is not currently in the FragmentManager");
+            throwException(new IllegalStateException("Fragment " + fragment
+                    + " is not currently in the FragmentManager"));
         }
         if (fragment.mState > Fragment.INITIALIZING) {
             Bundle result = saveFragmentBasicState(fragment);
@@ -913,7 +847,11 @@
                             if (f.mContainerId != 0) {
                                 container = (ViewGroup)mActivity.findViewById(f.mContainerId);
                                 if (container == null && !f.mRestored) {
-                                    throwNoViewFound(f);
+                                    throwException(new IllegalArgumentException(
+                                            "No view found for id 0x"
+                                            + Integer.toHexString(f.mContainerId) + " ("
+                                            + f.getResources().getResourceName(f.mContainerId)
+                                            + ") for fragment " + f));
                                 }
                             }
                             f.mContainer = container;
@@ -1674,12 +1612,9 @@
             Fragment f = mActive.get(i);
             if (f != null) {
                 if (f.mIndex < 0) {
-                    String msg = "Failure saving state: active " + f
-                            + " has cleared index: " + f.mIndex;
-                    Slog.e(TAG, msg);
-                    dump("  ", null, new PrintWriter(new LogWriter(
-                            Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                    throw new IllegalStateException(msg);
+                    throwException(new IllegalStateException(
+                            "Failure saving state: active " + f
+                            + " has cleared index: " + f.mIndex));
                 }
 
                 haveFragments = true;
@@ -1692,12 +1627,9 @@
 
                     if (f.mTarget != null) {
                         if (f.mTarget.mIndex < 0) {
-                            String msg = "Failure saving state: " + f
-                                + " has target not in fragment manager: " + f.mTarget;
-                            Slog.e(TAG, msg);
-                            dump("  ", null, new PrintWriter(new LogWriter(
-                                    Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                            throw new IllegalStateException(msg);
+                            throwException(new IllegalStateException(
+                                    "Failure saving state: " + f
+                                    + " has target not in fragment manager: " + f.mTarget));
                         }
                         if (fs.mSavedFragmentState == null) {
                             fs.mSavedFragmentState = new Bundle();
@@ -1736,12 +1668,9 @@
                 for (int i=0; i<N; i++) {
                     added[i] = mAdded.get(i).mIndex;
                     if (added[i] < 0) {
-                        String msg = "Failure saving state: active " + mAdded.get(i)
-                                + " has cleared index: " + added[i];
-                        Slog.e(TAG, msg);
-                        dump("  ", null, new PrintWriter(new LogWriter(
-                                Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
-                        throw new IllegalStateException(msg);
+                        throwException(new IllegalStateException(
+                                "Failure saving state: active " + mAdded.get(i)
+                                + " has cleared index: " + added[i]));
                     }
                     if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
                             + ": " + mAdded.get(i));
@@ -1846,8 +1775,8 @@
             for (int i=0; i<fms.mAdded.length; i++) {
                 Fragment f = mActive.get(fms.mAdded[i]);
                 if (f == null) {
-                    throw new IllegalStateException(
-                            "No instantiated fragment for index #" + fms.mAdded[i]);
+                    throwException(new IllegalStateException(
+                            "No instantiated fragment for index #" + fms.mAdded[i]));
                 }
                 f.mAdded = true;
                 if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
@@ -1875,7 +1804,7 @@
     }
     
     public void attachActivity(Activity activity) {
-        if (mActivity != null) throw new IllegalStateException();
+        if (mActivity != null) throw new IllegalStateException("Already attached");
         mActivity = activity;
     }
     
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index ef61af7..22a21cd 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -16,13 +16,12 @@
 
 package android.app;
 
-import android.content.Context;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.IBinder;
-import android.os.ServiceManager;
 import android.view.IWindowManager;
 import android.view.IOnKeyguardExitResult;
+import android.view.WindowManagerGlobal;
 
 /**
  * Class that can be used to lock and unlock the keyboard. Get an instance of this 
@@ -111,7 +110,7 @@
 
 
     KeyguardManager() {
-        mWM = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
+        mWM = WindowManagerGlobal.getWindowManagerService();
     }
 
     /**
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 27843ac..1ad2e6d 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -43,6 +43,7 @@
 import android.util.Log;
 import android.view.ViewRootImpl;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -689,7 +690,7 @@
     public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -727,7 +728,7 @@
             int x, int y, int z, Bundle extras) {
         try {
             //Log.v(TAG, "Sending new wallpaper offsets from app...");
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
                     windowToken, action, x, y, z, extras, false);
             //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
@@ -747,7 +748,7 @@
      */
     public void clearWallpaperOffsets(IBinder windowToken) {
         try {
-            ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+            WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, -1, -1, -1, -1);
         } catch (RemoteException e) {
             // Ignore.
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 2c19c0c..c76bf91 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -29,6 +29,7 @@
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
 
 import com.android.internal.appwidget.IAppWidgetHost;
 import com.android.internal.appwidget.IAppWidgetService;
@@ -83,7 +84,7 @@
         public UpdateHandler(Looper looper) {
             super(looper);
         }
-        
+
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case HANDLE_UPDATE: {
@@ -105,16 +106,25 @@
             }
         }
     }
-    
+
     Handler mHandler;
 
     int mHostId;
     Callbacks mCallbacks = new Callbacks();
     final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
+    private OnClickHandler mOnClickHandler;
 
     public AppWidgetHost(Context context, int hostId) {
+        this(context, hostId, null);
+    }
+
+    /**
+     * @hide
+     */
+    public AppWidgetHost(Context context, int hostId, OnClickHandler handler) {
         mContext = context;
         mHostId = hostId;
+        mOnClickHandler = handler;
         mHandler = new UpdateHandler(context.getMainLooper());
         mDisplayMetrics = context.getResources().getDisplayMetrics();
         synchronized (sServiceLock) {
@@ -132,7 +142,7 @@
     public void startListening() {
         int[] updatedIds;
         ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
-        
+
         try {
             if (mPackageName == null) {
                 mPackageName = mContext.getPackageName();
@@ -180,7 +190,7 @@
     }
 
     /**
-     * Stop listening to changes for this AppWidget.  
+     * Stop listening to changes for this AppWidget.
      */
     public void deleteAppWidgetId(int appWidgetId) {
         synchronized (mViews) {
@@ -235,6 +245,7 @@
     public final AppWidgetHostView createView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
         AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
+        view.setOnClickHandler(mOnClickHandler);
         view.setAppWidget(appWidgetId, appWidget);
         synchronized (mViews) {
             mViews.put(appWidgetId, view);
@@ -246,6 +257,7 @@
             throw new RuntimeException("system server dead?", e);
         }
         view.updateAppWidget(views);
+
         return view;
     }
 
@@ -255,7 +267,7 @@
      */
     protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
-        return new AppWidgetHostView(context);
+        return new AppWidgetHostView(context, mOnClickHandler);
     }
 
     /**
@@ -265,7 +277,7 @@
         AppWidgetHostView v;
 
         // Convert complex to dp -- we are getting the AppWidgetProviderInfo from the
-        // AppWidgetService, which doesn't have our context, hence we need to do the 
+        // AppWidgetService, which doesn't have our context, hence we need to do the
         // conversion here.
         appWidget.minWidth =
             TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index ed95ae5..603ceb7 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -44,6 +44,7 @@
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.RemoteViews;
+import android.widget.RemoteViews.OnClickHandler;
 import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
 import android.widget.TextView;
 
@@ -83,7 +84,8 @@
     long mFadeStartTime = -1;
     Bitmap mOld;
     Paint mOldPaint = new Paint();
-    
+    private OnClickHandler mOnClickHandler;
+
     /**
      * Create a host view.  Uses default fade animations.
      */
@@ -92,9 +94,17 @@
     }
 
     /**
+     * @hide
+     */
+    public AppWidgetHostView(Context context, OnClickHandler handler) {
+        this(context, android.R.anim.fade_in, android.R.anim.fade_out);
+        mOnClickHandler = handler;
+    }
+
+    /**
      * Create a host view. Uses specified animations when pushing
      * {@link #updateAppWidget(RemoteViews)}.
-     * 
+     *
      * @param animationIn Resource ID of in animation to use
      * @param animationOut Resource ID of out animation to use
      */
@@ -109,6 +119,17 @@
     }
 
     /**
+     * Pass the given handler to RemoteViews when updating this widget. Unless this
+     * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
+     * should be made.
+     * @param handler
+     * @hide
+     */
+    public void setOnClickHandler(OnClickHandler handler) {
+        mOnClickHandler = handler;
+    }
+
+    /**
      * Set the AppWidget that will be displayed by this view. This method also adds default padding
      * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
      * and can be overridden in order to add custom padding.
@@ -177,7 +198,7 @@
     public int getAppWidgetId() {
         return mAppWidgetId;
     }
-    
+
     public AppWidgetProviderInfo getAppWidgetInfo() {
         return mInfo;
     }
@@ -281,12 +302,13 @@
      * AppWidget provider. Will animate into these new views as needed
      */
     public void updateAppWidget(RemoteViews remoteViews) {
+
         if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
 
         boolean recycled = false;
         View content = null;
         Exception exception = null;
-        
+
         // Capture the old view into a bitmap so we can do the crossfade.
         if (CROSSFADE) {
             if (mFadeStartTime < 0) {
@@ -305,7 +327,7 @@
                 }
             }
         }
-        
+
         if (remoteViews == null) {
             if (mViewMode == VIEW_MODE_DEFAULT) {
                 // We've already done this -- nothing to do.
@@ -324,7 +346,7 @@
             // layout matches, try recycling it
             if (content == null && layoutId == mLayoutId) {
                 try {
-                    remoteViews.reapply(mContext, mView);
+                    remoteViews.reapply(mContext, mView, mOnClickHandler);
                     content = mView;
                     recycled = true;
                     if (LOGD) Log.d(TAG, "was able to recycled existing layout");
@@ -332,11 +354,11 @@
                     exception = e;
                 }
             }
-            
+
             // Try normal RemoteView inflation
             if (content == null) {
                 try {
-                    content = remoteViews.apply(mContext, this);
+                    content = remoteViews.apply(mContext, this, mOnClickHandler);
                     if (LOGD) Log.d(TAG, "had to inflate new layout");
                 } catch (RuntimeException e) {
                     exception = e;
@@ -346,7 +368,7 @@
             mLayoutId = layoutId;
             mViewMode = VIEW_MODE_CONTENT;
         }
-        
+
         if (content == null) {
             if (mViewMode == VIEW_MODE_ERROR) {
                 // We've already done this -- nothing to do.
@@ -356,7 +378,7 @@
             content = getErrorView();
             mViewMode = VIEW_MODE_ERROR;
         }
-        
+
         if (!recycled) {
             prepareView(content);
             addView(content);
@@ -455,7 +477,7 @@
             return super.drawChild(canvas, child, drawingTime);
         }
     }
-    
+
     /**
      * Prepare the given view to be shown. This might include adjusting
      * {@link FrameLayout.LayoutParams} before inserting.
@@ -471,7 +493,7 @@
         requested.gravity = Gravity.CENTER;
         view.setLayoutParams(requested);
     }
-    
+
     /**
      * Inflate and return the default layout requested by AppWidget provider.
      */
@@ -481,7 +503,7 @@
         }
         View defaultView = null;
         Exception exception = null;
-        
+
         try {
             if (mInfo != null) {
                 Context theirContext = mContext.createPackageContext(
@@ -500,19 +522,19 @@
         } catch (RuntimeException e) {
             exception = e;
         }
-        
+
         if (exception != null) {
             Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString());
         }
-        
+
         if (defaultView == null) {
             if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
             defaultView = getErrorView();
         }
-        
+
         return defaultView;
     }
-    
+
     /**
      * Inflate and return a view that represents an error state.
      */
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 8a69c3a..23d8f46 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -279,7 +279,7 @@
             final int uid = Binder.getCallingUid();
             String missingPerm = null;
 
-            if (uid == mMyUid) {
+            if (UserHandle.isSameApp(uid, mMyUid)) {
                 return;
             }
 
@@ -340,7 +340,7 @@
             final int uid = Binder.getCallingUid();
             String missingPerm = null;
 
-            if (uid == mMyUid) {
+            if (UserHandle.isSameApp(uid, mMyUid)) {
                 return;
             }
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a70bf6c..1460bf5 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -34,6 +34,7 @@
 import android.os.Looper;
 import android.os.UserHandle;
 import android.util.AttributeSet;
+import android.view.CompatibilityInfoHolder;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -2464,6 +2465,16 @@
     public abstract Context createConfigurationContext(Configuration overrideConfiguration);
 
     /**
+     * Gets the compatibility info holder for this context.  This information
+     * is provided on a per-application basis and is used to simulate lower density
+     * display metrics for legacy applications.
+     *
+     * @return The compatibility info holder, or null if not required by the application.
+     * @hide
+     */
+    public abstract CompatibilityInfoHolder getCompatibilityInfo();
+
+    /**
      * Indicates whether this Context is restricted.
      *
      * @return True if this Context is restricted, false otherwise.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 75842be..3a13725 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -31,6 +31,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
+import android.view.CompatibilityInfoHolder;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -543,4 +544,10 @@
     public boolean isRestricted() {
         return mBase.isRestricted();
     }
+
+    /** @hide */
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        return mBase.getCompatibilityInfo();
+    }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 0190555..06edf32 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -571,7 +571,7 @@
  *     <li> {@link #EXTRA_INITIAL_INTENTS}
  *     <li> {@link #EXTRA_INTENT}
  *     <li> {@link #EXTRA_KEY_EVENT}
- *     <li> {@link #EXTRA_ORIGINATING_URL}
+ *     <li> {@link #EXTRA_ORIGINATING_URI}
  *     <li> {@link #EXTRA_PHONE_NUMBER}
  *     <li> {@link #EXTRA_REFERRER}
  *     <li> {@link #EXTRA_REMOTE_INTENT_TOKEN}
@@ -1288,17 +1288,17 @@
             = "android.intent.extra.NOT_UNKNOWN_SOURCE";
 
     /**
-     * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
-     * {@link #ACTION_VIEW} to indicate the URL from which the local APK in the Intent
+     * Used as a URI extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link #ACTION_VIEW} to indicate the URI from which the local APK in the Intent
      * data field originated from.
      */
-    public static final String EXTRA_ORIGINATING_URL
-            = "android.intent.extra.ORIGINATING_URL";
+    public static final String EXTRA_ORIGINATING_URI
+            = "android.intent.extra.ORIGINATING_URI";
 
     /**
-     * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
-     * {@link #ACTION_VIEW} to indicate the HTTP referrer associated with the Intent
-     * data field or {@link #EXTRA_ORIGINATING_URL}.
+     * Used as a URI extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link #ACTION_VIEW} to indicate the HTTP referrer URI associated with the Intent
+     * data field or {@link #EXTRA_ORIGINATING_URI}.
      */
     public static final String EXTRA_REFERRER
             = "android.intent.extra.REFERRER";
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 22807a4..3f4b994 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -39,6 +39,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
@@ -200,7 +201,7 @@
     List<PackageInfo> getPreferredPackages(int flags);
 
     void addPreferredActivity(in IntentFilter filter, int match,
-            in ComponentName[] set, in ComponentName activity);
+            in ComponentName[] set, in ComponentName activity, int userId);
 
     void replacePreferredActivity(in IntentFilter filter, int match,
             in ComponentName[] set, in ComponentName activity);
@@ -304,10 +305,11 @@
      * Get package statistics including the code, data and cache size for
      * an already installed package
      * @param packageName The package name of the application
+     * @param userHandle Which user the size should be retrieved for
      * @param observer a callback to use to notify when the asynchronous
      * retrieval of information is complete.
      */
-    void getPackageSizeInfo(in String packageName, IPackageStatsObserver observer);
+    void getPackageSizeInfo(in String packageName, int userHandle, IPackageStatsObserver observer);
     
     /**
      * Get a list of shared libraries that are available on the
@@ -362,6 +364,11 @@
             int flags, in String installerPackageName, in Uri verificationURI,
             in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams);
 
+    void installPackageWithVerificationAndEncryption(in Uri packageURI,
+            in IPackageInstallObserver observer, int flags, in String installerPackageName,
+            in VerificationParams verificationParams,
+            in ContainerEncryptionParams encryptionParams);
+
     void verifyPendingInstall(int id, int verificationCode);
 
     VerifierDeviceIdentity getVerifierDeviceIdentity();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f287ca5..0461dd1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -28,6 +28,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Environment;
+import android.os.UserHandle;
 import android.util.AndroidException;
 import android.util.DisplayMetrics;
 
@@ -2227,6 +2228,37 @@
             ContainerEncryptionParams encryptionParams);
 
     /**
+     * Similar to
+     * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
+     * with an extra verification information provided.
+     *
+     * @param packageURI The location of the package file to install. This can
+     *            be a 'file:' or a 'content:' URI.
+     * @param observer An observer callback to get notified when the package
+     *            installation is complete.
+     *            {@link IPackageInstallObserver#packageInstalled(String, int)}
+     *            will be called when that happens. observer may be null to
+     *            indicate that no callback is desired.
+     * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+     *            {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}
+     *            .
+     * @param installerPackageName Optional package name of the application that
+     *            is performing the installation. This identifies which market
+     *            the package came from.
+     * @param verificationParams an object that holds signal information to
+     *            assist verification. May be {@code null}.
+     * @param encryptionParams if the package to be installed is encrypted,
+     *            these parameters describing the encryption and authentication
+     *            used. May be {@code null}.
+     *
+     * @hide
+     */
+    public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams,
+            ContainerEncryptionParams encryptionParams);
+
+    /**
      * Allows a package listening to the
      * {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION package verification
      * broadcast} to respond to the package manager. The response must include
@@ -2376,6 +2408,7 @@
      * should have the {@link android.Manifest.permission#GET_PACKAGE_SIZE} permission.
      *
      * @param packageName The name of the package whose size information is to be retrieved
+     * @param userHandle The user whose size information should be retrieved.
      * @param observer An observer callback to get notified when the operation
      * is complete.
      * {@link android.content.pm.IPackageStatsObserver#onGetStatsCompleted(PackageStats, boolean)}
@@ -2386,10 +2419,20 @@
      *
      * @hide
      */
-    public abstract void getPackageSizeInfo(String packageName,
+    public abstract void getPackageSizeInfo(String packageName, int userHandle,
             IPackageStatsObserver observer);
 
     /**
+     * Like {@link #getPackageSizeInfo(String, int, IPackageStatsObserver)}, but
+     * returns the size for the calling user.
+     *
+     * @hide
+     */
+    public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
+        getPackageSizeInfo(packageName, UserHandle.myUserId(), observer);
+    }
+
+    /**
      * @deprecated This function no longer does anything; it was an old
      * approach to managing preferred activities, which has been superceeded
      * (and conflicts with) the modern activity-based preferences.
@@ -2460,6 +2503,17 @@
             ComponentName[] set, ComponentName activity);
 
     /**
+     * Same as {@link #addPreferredActivity(IntentFilter, int,
+            ComponentName[], ComponentName)}, but with a specific userId to apply the preference
+            to.
+     * @hide
+     */
+    public void addPreferredActivity(IntentFilter filter, int match,
+            ComponentName[] set, ComponentName activity, int userId) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * @deprecated This is a protected API that should not have been available
      * to third party applications.  It is the platform's responsibility for
      * assigning preferred activities and this can not be directly modified.
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 1205da7..cb9039b 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 
 /**
  * implementation of PackageStats associated with a
@@ -27,6 +28,9 @@
     /** Name of the package to which this stats applies. */
     public String packageName;
 
+    /** @hide */
+    public int userHandle;
+
     /** Size of the code (e.g., APK) */
     public long codeSize;
 
@@ -78,33 +82,58 @@
     public String toString() {
         final StringBuilder sb = new StringBuilder("PackageStats{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
-        sb.append(" packageName=");
+        sb.append(" ");
         sb.append(packageName);
-        sb.append(",codeSize=");
-        sb.append(codeSize);
-        sb.append(",dataSize=");
-        sb.append(dataSize);
-        sb.append(",cacheSize=");
-        sb.append(cacheSize);
-        sb.append(",externalCodeSize=");
-        sb.append(externalCodeSize);
-        sb.append(",externalDataSize=");
-        sb.append(externalDataSize);
-        sb.append(",externalCacheSize=");
-        sb.append(externalCacheSize);
-        sb.append(",externalMediaSize=");
-        sb.append(externalMediaSize);
-        sb.append(",externalObbSize=");
-        sb.append(externalObbSize);
+        if (codeSize != 0) {
+            sb.append(" code=");
+            sb.append(codeSize);
+        }
+        if (dataSize != 0) {
+            sb.append(" data=");
+            sb.append(dataSize);
+        }
+        if (cacheSize != 0) {
+            sb.append(" cache=");
+            sb.append(cacheSize);
+        }
+        if (externalCodeSize != 0) {
+            sb.append(" extCode=");
+            sb.append(externalCodeSize);
+        }
+        if (externalDataSize != 0) {
+            sb.append(" extData=");
+            sb.append(externalDataSize);
+        }
+        if (externalCacheSize != 0) {
+            sb.append(" extCache=");
+            sb.append(externalCacheSize);
+        }
+        if (externalMediaSize != 0) {
+            sb.append(" media=");
+            sb.append(externalMediaSize);
+        }
+        if (externalObbSize != 0) {
+            sb.append(" obb=");
+            sb.append(externalObbSize);
+        }
+        sb.append("}");
         return sb.toString();
     }
 
     public PackageStats(String pkgName) {
         packageName = pkgName;
+        userHandle = UserHandle.myUserId();
+    }
+
+    /** @hide */
+    public PackageStats(String pkgName, int userHandle) {
+        this.packageName = pkgName;
+        this.userHandle = userHandle;
     }
 
     public PackageStats(Parcel source) {
         packageName = source.readString();
+        userHandle = source.readInt();
         codeSize = source.readLong();
         dataSize = source.readLong();
         cacheSize = source.readLong();
@@ -117,6 +146,7 @@
 
     public PackageStats(PackageStats pStats) {
         packageName = pStats.packageName;
+        userHandle = pStats.userHandle;
         codeSize = pStats.codeSize;
         dataSize = pStats.dataSize;
         cacheSize = pStats.cacheSize;
@@ -133,6 +163,7 @@
 
     public void writeToParcel(Parcel dest, int parcelableFlags){
         dest.writeString(packageName);
+        dest.writeInt(userHandle);
         dest.writeLong(codeSize);
         dest.writeLong(dataSize);
         dest.writeLong(cacheSize);
diff --git a/core/java/android/content/pm/VerificationParams.aidl b/core/java/android/content/pm/VerificationParams.aidl
new file mode 100644
index 0000000..5bb7f6962
--- /dev/null
+++ b/core/java/android/content/pm/VerificationParams.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012, 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.pm;
+
+parcelable VerificationParams;
diff --git a/core/java/android/content/pm/VerificationParams.java b/core/java/android/content/pm/VerificationParams.java
new file mode 100644
index 0000000..9bec87e
--- /dev/null
+++ b/core/java/android/content/pm/VerificationParams.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2012 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.pm;
+
+import android.content.pm.ManifestDigest;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents verification parameters used to verify packages to be installed.
+ *
+ * @hide
+ */
+public class VerificationParams implements Parcelable {
+    /** What we print out first when toString() is called. */
+    private static final String TO_STRING_PREFIX = "VerificationParams{";
+
+    /** The location of the supplementary verification file. */
+    private final Uri mVerificationURI;
+
+    /** URI referencing where the package was downloaded from. */
+    private final Uri mOriginatingURI;
+
+    /** HTTP referrer URI associated with the originatingURI. */
+    private final Uri mReferrer;
+
+    /**
+     * An object that holds the digest of the package which can be used to
+     * verify ownership.
+     */
+    private final ManifestDigest mManifestDigest;
+
+    /**
+     * Creates verification specifications for installing with application verification.
+     *
+     * @param verificationURI The location of the supplementary verification
+     *            file. This can be a 'file:' or a 'content:' URI. May be {@code null}.
+     * @param originatingURI URI referencing where the package was downloaded
+     *            from. May be {@code null}.
+     * @param referrer HTTP referrer URI associated with the originatingURI.
+     *            May be {@code null}.
+     * @param manifestDigest an object that holds the digest of the package
+     *            which can be used to verify ownership. May be {@code null}.
+     */
+    public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
+            ManifestDigest manifestDigest) {
+        mVerificationURI = verificationURI;
+        mOriginatingURI = originatingURI;
+        mReferrer = referrer;
+        mManifestDigest = manifestDigest;
+    }
+
+    public Uri getVerificationURI() {
+        return mVerificationURI;
+    }
+
+    public Uri getOriginatingURI() {
+        return mOriginatingURI;
+    }
+
+    public Uri getReferrer() {
+        return mReferrer;
+    }
+
+    public ManifestDigest getManifestDigest() {
+        return mManifestDigest;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof VerificationParams)) {
+            return false;
+        }
+
+        final VerificationParams other = (VerificationParams) o;
+
+        if (mVerificationURI == null && other.mVerificationURI != null) {
+            return false;
+        }
+        if (!mVerificationURI.equals(other.mVerificationURI)) {
+            return false;
+        }
+
+        if (mOriginatingURI == null && other.mOriginatingURI != null) {
+            return false;
+        }
+        if (!mOriginatingURI.equals(other.mOriginatingURI)) {
+            return false;
+        }
+
+        if (mReferrer == null && other.mReferrer != null) {
+            return false;
+        }
+        if (!mReferrer.equals(other.mReferrer)) {
+            return false;
+        }
+
+        if (mManifestDigest == null && other.mManifestDigest != null) {
+            return false;
+        }
+        if (mManifestDigest != null && !mManifestDigest.equals(other.mManifestDigest)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 3;
+
+        hash += 5 * (mVerificationURI==null?1:mVerificationURI.hashCode());
+        hash += 7 * (mOriginatingURI==null?1:mOriginatingURI.hashCode());
+        hash += 11 * (mReferrer==null?1:mReferrer.hashCode());
+        hash += 13 * (mManifestDigest==null?1:mManifestDigest.hashCode());
+
+        return hash;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
+
+        sb.append("mVerificationURI=");
+        sb.append(mVerificationURI.toString());
+        sb.append(",mOriginatingURI=");
+        sb.append(mOriginatingURI.toString());
+        sb.append(",mReferrer=");
+        sb.append(mReferrer.toString());
+        sb.append(",mManifestDigest=");
+        sb.append(mManifestDigest.toString());
+        sb.append('}');
+
+        return sb.toString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mVerificationURI, 0);
+        dest.writeParcelable(mOriginatingURI, 0);
+        dest.writeParcelable(mReferrer, 0);
+        dest.writeParcelable(mManifestDigest, 0);
+    }
+
+
+    private VerificationParams(Parcel source) {
+        mVerificationURI = source.readParcelable(Uri.class.getClassLoader());
+        mOriginatingURI = source.readParcelable(Uri.class.getClassLoader());
+        mReferrer = source.readParcelable(Uri.class.getClassLoader());
+        mManifestDigest = source.readParcelable(ManifestDigest.class.getClassLoader());
+    }
+
+    public static final Parcelable.Creator<VerificationParams> CREATOR =
+            new Parcelable.Creator<VerificationParams>() {
+        public VerificationParams createFromParcel(Parcel source) {
+                return new VerificationParams(source);
+        }
+
+        public VerificationParams[] newArray(int size) {
+            return new VerificationParams[size];
+        }
+    };
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 640044b..a73115c 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -17,12 +17,20 @@
 package android.hardware.display;
 
 import android.content.Context;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
+import android.util.SparseArray;
+import android.view.CompatibilityInfoHolder;
+import android.view.Display;
 import android.view.DisplayInfo;
 
+import java.util.ArrayList;
+
 /**
  * Manages the properties, media routing and power state of attached displays.
  * <p>
@@ -34,25 +42,41 @@
  */
 public final class DisplayManager {
     private static final String TAG = "DisplayManager";
+    private static final boolean DEBUG = false;
+
+    private static final int MSG_DISPLAY_ADDED = 1;
+    private static final int MSG_DISPLAY_REMOVED = 2;
+    private static final int MSG_DISPLAY_CHANGED = 3;
 
     private static DisplayManager sInstance;
 
     private final IDisplayManager mDm;
 
+    // Guarded by mDisplayLock
+    private final Object mDisplayLock = new Object();
+    private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
+            new ArrayList<DisplayListenerDelegate>();
+
+
     private DisplayManager(IDisplayManager dm) {
         mDm = dm;
     }
 
     /**
      * Gets an instance of the display manager.
-     * @return The display manager instance.
+     *
+     * @return The display manager instance, may be null early in system startup
+     * before the display manager has been fully initialized.
+     *
      * @hide
      */
     public static DisplayManager getInstance() {
         synchronized (DisplayManager.class) {
             if (sInstance == null) {
                 IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
-                sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b));
+                if (b != null) {
+                    sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b));
+                }
             }
             return sInstance;
         }
@@ -74,4 +98,161 @@
             return false;
         }
     }
+
+    /**
+     * Gets information about a logical display.
+     *
+     * The display metrics may be adjusted to provide compatibility
+     * for legacy applications.
+     *
+     * @param displayId The logical display id.
+     * @param applicationContext The application context from which to obtain
+     * compatible metrics.
+     * @return The display object.
+     */
+    public Display getDisplay(int displayId, Context applicationContext) {
+        if (applicationContext == null) {
+            throw new IllegalArgumentException("applicationContext must not be null");
+        }
+
+        CompatibilityInfoHolder cih = null;
+        if (displayId == Display.DEFAULT_DISPLAY) {
+            cih = applicationContext.getCompatibilityInfo();
+        }
+        return getCompatibleDisplay(displayId, cih);
+    }
+
+    /**
+     * Gets information about a logical display.
+     *
+     * The display metrics may be adjusted to provide compatibility
+     * for legacy applications.
+     *
+     * @param displayId The logical display id.
+     * @param cih The compatibility info, or null if none is required.
+     * @return The display object.
+     *
+     * @hide
+     */
+    public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) {
+        return new Display(displayId, cih);
+    }
+
+    /**
+     * Gets information about a logical display without applying any compatibility metrics.
+     *
+     * @param displayId The logical display id.
+     * @return The display object.
+     *
+     * @hide
+     */
+    public Display getRealDisplay(int displayId) {
+        return getCompatibleDisplay(displayId, null);
+    }
+
+    /**
+     * Registers an display listener to receive notifications about when
+     * displays are added, removed or changed.
+     *
+     * @param listener The listener to register.
+     * @param handler The handler on which the listener should be invoked, or null
+     * if the listener should be invoked on the calling thread's looper.
+     *
+     * @see #unregisterDisplayListener
+     */
+    public void registerDisplayListener(DisplayListener listener, Handler handler) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mDisplayLock) {
+            int index = findDisplayListenerLocked(listener);
+            if (index < 0) {
+                mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
+            }
+        }
+    }
+
+    /**
+     * Unregisters an input device listener.
+     *
+     * @param listener The listener to unregister.
+     *
+     * @see #registerDisplayListener
+     */
+    public void unregisterDisplayListener(DisplayListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mDisplayLock) {
+            int index = findDisplayListenerLocked(listener);
+            if (index >= 0) {
+                DisplayListenerDelegate d = mDisplayListeners.get(index);
+                d.removeCallbacksAndMessages(null);
+                mDisplayListeners.remove(index);
+            }
+        }
+    }
+
+    private int findDisplayListenerLocked(DisplayListener listener) {
+        final int numListeners = mDisplayListeners.size();
+        for (int i = 0; i < numListeners; i++) {
+            if (mDisplayListeners.get(i).mListener == listener) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Listens for changes in available display devices.
+     */
+    public interface DisplayListener {
+        /**
+         * Called whenever a logical display has been added to the system.
+         * Use {@link DisplayManager#getDisplay} to get more information about the display.
+         *
+         * @param displayId The id of the logical display that was added.
+         */
+        void onDisplayAdded(int displayId);
+
+        /**
+         * Called whenever a logical display has been removed from the system.
+         *
+         * @param displayId The id of the logical display that was removed.
+         */
+        void onDisplayRemoved(int displayId);
+
+        /**
+         * Called whenever the properties of a logical display have changed.
+         *
+         * @param displayId The id of the logical display that changed.
+         */
+        void onDisplayChanged(int displayId);
+    }
+
+    private static final class DisplayListenerDelegate extends Handler {
+        public final DisplayListener mListener;
+
+        public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
+            super(handler != null ? handler.getLooper() : Looper.myLooper());
+            mListener = listener;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_DISPLAY_ADDED:
+                    mListener.onDisplayAdded(msg.arg1);
+                    break;
+                case MSG_DISPLAY_REMOVED:
+                    mListener.onDisplayRemoved(msg.arg1);
+                    break;
+                case MSG_DISPLAY_CHANGED:
+                    mListener.onDisplayChanged(msg.arg1);
+                    break;
+            }
+        }
+    }
 }
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 9bab797..98bd4f5 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -87,4 +87,12 @@
 
     /* Sets the file path for USB mass storage backing file. */
     void setMassStorageBackingFile(String path);
+
+    /* Allow USB debugging from the attached host. If alwaysAllow is true, add the
+     * the public key to list of host keys that the user has approved.
+     */
+    void allowUsbDebugging(boolean alwaysAllow, String publicKey);
+
+    /* Deny USB debugging from the attached host */
+    void denyUsbDebugging();
 }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index a9de289..d5b9edc 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -39,7 +39,6 @@
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
-import android.view.Display;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -630,7 +629,7 @@
         if (mWindow != null) {
             throw new IllegalStateException("Must be called before onCreate()");
         }
-        if (ActivityManager.isHighEndGfx(new Display(Display.DEFAULT_DISPLAY, null))) {
+        if (ActivityManager.isHighEndGfx()) {
             mHardwareAccelerated = true;
             return true;
         }
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 00438a1..d59fa6a 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -184,8 +184,17 @@
                 if (!TextUtils.equals(apnType, mApnType)) {
                     return;
                 }
-                mNetworkInfo.setSubtype(TelephonyManager.getDefault().getNetworkType(),
-                        TelephonyManager.getDefault().getNetworkTypeName());
+
+                int oldSubtype = mNetworkInfo.getSubtype();
+                int newSubType = TelephonyManager.getDefault().getNetworkType();
+                String subTypeName = TelephonyManager.getDefault().getNetworkTypeName();
+                mNetworkInfo.setSubtype(newSubType, subTypeName);
+                if (newSubType != oldSubtype && mNetworkInfo.isConnected()) {
+                    Message msg = mTarget.obtainMessage(EVENT_NETWORK_SUBTYPE_CHANGED,
+                                                        oldSubtype, 0, mNetworkInfo);
+                    msg.sendToTarget();
+                }
+
                 PhoneConstants.DataState state = Enum.valueOf(PhoneConstants.DataState.class,
                         intent.getStringExtra(PhoneConstants.STATE_KEY));
                 String reason = intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY);
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 313c174..eae89f1c 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -63,6 +63,12 @@
     public static final int EVENT_RESTORE_DEFAULT_NETWORK = 6;
 
     /**
+     * msg.what = EVENT_NETWORK_SUBTYPE_CHANGED
+     * msg.obj = NetworkInfo object
+     */
+    public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 7;
+
+    /**
      * -------------------------------------------------------------
      * Control Interface
      * -------------------------------------------------------------
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index c62715b..7b16f4d 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -115,4 +115,6 @@
     public static final int BATTERY_PLUGGED_AC = 1;
     /** Power source is a USB port. */
     public static final int BATTERY_PLUGGED_USB = 2;
+    /** Power source is wireless. */
+    public static final int BATTERY_PLUGGED_WIRELESS = 4;
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index fcc0ae4..54f2fe3 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2071,6 +2071,9 @@
                         case BatteryManager.BATTERY_PLUGGED_USB:
                             pw.print("usb");
                             break;
+                        case BatteryManager.BATTERY_PLUGGED_WIRELESS:
+                            pw.print("wireless");
+                            break;
                         default:
                             pw.print(oldPlug);
                             break;
diff --git a/core/java/android/os/FactoryTest.java b/core/java/android/os/FactoryTest.java
new file mode 100644
index 0000000..ec99697
--- /dev/null
+++ b/core/java/android/os/FactoryTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 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.os;
+
+/**
+ * Provides support for in-place factory test functions.
+ *
+ * This class provides a few properties that alter the normal operation of the system
+ * during factory testing.
+ *
+ * {@hide}
+ */
+public final class FactoryTest {
+    /**
+     * When true, long-press on power should immediately cause the device to
+     * shut down, without prompting the user.
+     */
+    public static boolean isLongPressOnPowerOffEnabled() {
+        return SystemProperties.getInt("factory.long_press_power_off", 0) != 0;
+    }
+}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 7c103aa..0941d71 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -53,8 +53,6 @@
 
     public static native int setPermissions(String file, int mode, int uid, int gid);
 
-    public static native int setUMask(int mask);
-
     /** returns the FAT file system volume ID for the volume mounted 
      * at the given mount point, or -1 for failure
      * @param mountPoint point for FAT volume
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
index b924e84..d33382b 100644
--- a/core/java/android/os/UEventObserver.java
+++ b/core/java/android/os/UEventObserver.java
@@ -37,14 +37,79 @@
  * @hide
 */
 public abstract class UEventObserver {
-    private static final String TAG = UEventObserver.class.getSimpleName();
+    private static UEventThread sThread;
+
+    private static native void native_setup();
+    private static native int next_event(byte[] buffer);
+
+    public UEventObserver() {
+    }
+
+    protected void finalize() throws Throwable {
+        try {
+            stopObserving();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private static UEventThread getThread() {
+        synchronized (UEventObserver.class) {
+            if (sThread == null) {
+                sThread = new UEventThread();
+                sThread.start();
+            }
+            return sThread;
+        }
+    }
+
+    private static UEventThread peekThread() {
+        synchronized (UEventObserver.class) {
+            return sThread;
+        }
+    }
+
+    /**
+     * Begin observation of UEvent's.<p>
+     * This method will cause the UEvent thread to start if this is the first
+     * invocation of startObserving in this process.<p>
+     * Once called, the UEvent thread will call onUEvent() when an incoming
+     * UEvent matches the specified string.<p>
+     * This method can be called multiple times to register multiple matches.
+     * Only one call to stopObserving is required even with multiple registered
+     * matches.
+     * @param match A substring of the UEvent to match. Use "" to match all
+     *              UEvent's
+     */
+    public final void startObserving(String match) {
+        final UEventThread t = getThread();
+        t.addObserver(match, this);
+    }
+
+    /**
+     * End observation of UEvent's.<p>
+     * This process's UEvent thread will never call onUEvent() on this
+     * UEventObserver after this call. Repeated calls have no effect.
+     */
+    public final void stopObserving() {
+        final UEventThread t = getThread();
+        if (t != null) {
+            t.removeObserver(this);
+        }
+    }
+
+    /**
+     * Subclasses of UEventObserver should override this method to handle
+     * UEvents.
+     */
+    public abstract void onUEvent(UEvent event);
 
     /**
      * Representation of a UEvent.
      */
-    static public class UEvent {
+    public static final class UEvent {
         // collection of key=value pairs parsed from the uevent message
-        public HashMap<String,String> mMap = new HashMap<String,String>();
+        private final HashMap<String,String> mMap = new HashMap<String,String>();
 
         public UEvent(String message) {
             int offset = 0;
@@ -79,20 +144,20 @@
         }
     }
 
-    private static UEventThread sThread;
-    private static boolean sThreadStarted = false;
-
-    private static class UEventThread extends Thread {
+    private static final class UEventThread extends Thread {
         /** Many to many mapping of string match to observer.
          *  Multimap would be better, but not available in android, so use
          *  an ArrayList where even elements are the String match and odd
          *  elements the corresponding UEventObserver observer */
-        private ArrayList<Object> mObservers = new ArrayList<Object>();
-        
-        UEventThread() {
+        private final ArrayList<Object> mKeysAndObservers = new ArrayList<Object>();
+
+        private final ArrayList<UEventObserver> mTempObserversToSignal =
+                new ArrayList<UEventObserver>();
+
+        public UEventThread() {
             super("UEventObserver");
         }
-        
+
         public void run() {
             native_setup();
 
@@ -101,91 +166,54 @@
             while (true) {
                 len = next_event(buffer);
                 if (len > 0) {
-                    String bufferStr = new String(buffer, 0, len);  // easier to search a String
-                    synchronized (mObservers) {
-                        for (int i = 0; i < mObservers.size(); i += 2) {
-                            if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {
-                                ((UEventObserver)mObservers.get(i+1))
-                                        .onUEvent(new UEvent(bufferStr));
-                            }
-                        }
-                    }
+                    sendEvent(new String(buffer, 0, len));
                 }
             }
         }
-        public void addObserver(String match, UEventObserver observer) {
-            synchronized(mObservers) {
-                mObservers.add(match);
-                mObservers.add(observer);
+
+        private void sendEvent(String message) {
+            synchronized (mKeysAndObservers) {
+                final int N = mKeysAndObservers.size();
+                for (int i = 0; i < N; i += 2) {
+                    final String key = (String)mKeysAndObservers.get(i);
+                    if (message.indexOf(key) != -1) {
+                        final UEventObserver observer =
+                                (UEventObserver)mKeysAndObservers.get(i + 1);
+                        mTempObserversToSignal.add(observer);
+                    }
+                }
+            }
+
+            if (!mTempObserversToSignal.isEmpty()) {
+                final UEvent event = new UEvent(message);
+                final int N = mTempObserversToSignal.size();
+                for (int i = 0; i < N; i++) {
+                    final UEventObserver observer = mTempObserversToSignal.get(i);
+                    observer.onUEvent(event);
+                }
+                mTempObserversToSignal.clear();
             }
         }
+
+        public void addObserver(String match, UEventObserver observer) {
+            synchronized (mKeysAndObservers) {
+                mKeysAndObservers.add(match);
+                mKeysAndObservers.add(observer);
+            }
+        }
+
         /** Removes every key/value pair where value=observer from mObservers */
         public void removeObserver(UEventObserver observer) {
-            synchronized(mObservers) {
-                boolean found = true;
-                while (found) {
-                    found = false;
-                    for (int i = 0; i < mObservers.size(); i += 2) {
-                        if (mObservers.get(i+1) == observer) {
-                            mObservers.remove(i+1);
-                            mObservers.remove(i);
-                            found = true;
-                            break;
-                        }
+            synchronized (mKeysAndObservers) {
+                for (int i = 0; i < mKeysAndObservers.size(); ) {
+                    if (mKeysAndObservers.get(i + 1) == observer) {
+                        mKeysAndObservers.remove(i + 1);
+                        mKeysAndObservers.remove(i);
+                    } else {
+                        i += 2;
                     }
                 }
             }
         }
     }
-
-    private static native void native_setup();
-    private static native int next_event(byte[] buffer);
-
-    private static final synchronized void ensureThreadStarted() {
-        if (sThreadStarted == false) {
-            sThread = new UEventThread();
-            sThread.start();
-            sThreadStarted = true;
-        }
-    }
-
-    /**
-     * Begin observation of UEvent's.<p>
-     * This method will cause the UEvent thread to start if this is the first
-     * invocation of startObserving in this process.<p>
-     * Once called, the UEvent thread will call onUEvent() when an incoming
-     * UEvent matches the specified string.<p>
-     * This method can be called multiple times to register multiple matches.
-     * Only one call to stopObserving is required even with multiple registered
-     * matches.
-     * @param match A substring of the UEvent to match. Use "" to match all
-     *              UEvent's
-     */
-    public final synchronized void startObserving(String match) {
-        ensureThreadStarted();
-        sThread.addObserver(match, this);
-    }
-
-    /**
-     * End observation of UEvent's.<p>
-     * This process's UEvent thread will never call onUEvent() on this
-     * UEventObserver after this call. Repeated calls have no effect.
-     */
-    public final synchronized void stopObserving() {
-        sThread.removeObserver(this);
-    }
-
-    /**
-     * Subclasses of UEventObserver should override this method to handle
-     * UEvents.
-     */
-    public abstract void onUEvent(UEvent event);
-
-    protected void finalize() throws Throwable {
-        try {
-            stopObserving();
-        } finally {
-            super.finalize();
-        }
-    }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6dbba46..28273f0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1147,6 +1147,7 @@
          * <li>{@code 0} to never stay on while plugged in</li>
          * <li>{@link BatteryManager#BATTERY_PLUGGED_AC} to stay on for AC charger</li>
          * <li>{@link BatteryManager#BATTERY_PLUGGED_USB} to stay on for USB charger</li>
+         * <li>{@link BatteryManager#BATTERY_PLUGGED_WIRELESS} to stay on for wireless charger</li>
          * </ul>
          * These values can be OR-ed together.
          */
diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java
index fc3f501..5d6b17e 100644
--- a/core/java/android/service/dreams/DreamManagerService.java
+++ b/core/java/android/service/dreams/DreamManagerService.java
@@ -18,6 +18,7 @@
 import android.util.Slog;
 import android.view.IWindowManager;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 
 /**
  *
@@ -44,8 +45,7 @@
     public DreamManagerService(Context context) {
         if (DEBUG) Slog.v(TAG, "DreamManagerService startup");
         mContext = context;
-        mIWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
+        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
     }
 
     private void checkPermission(String permission) {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index b513915..efa8911 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -36,7 +36,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
-import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.LogPrinter;
@@ -51,9 +50,8 @@
 import android.view.SurfaceHolder;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewRootImpl;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -674,8 +672,8 @@
                             }
                         }
 
-                        redrawNeeded |= creating
-                                || (relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0;
+                        redrawNeeded |= creating || (relayoutResult
+                                & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
 
                         if (forceReport || creating || surfaceCreating
                                 || formatChanged || sizeChanged) {
@@ -762,7 +760,7 @@
             mWindowToken = wrapper.mWindowToken;
             mSurfaceHolder.setSizeFromLayout();
             mInitializing = true;
-            mSession = ViewRootImpl.getWindowSession(getMainLooper());
+            mSession = WindowManagerGlobal.getWindowSession(getMainLooper());
             
             mWindow.setSession(mSession);
 
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 7a174af..5e367cb 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -1282,6 +1282,7 @@
             }
         };
 
+        @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             Log.i(TAG, "Connected to " + name);
             synchronized(mStartLock) {
@@ -1305,6 +1306,7 @@
             return mCallback;
         }
 
+        @Override
         public void onServiceDisconnected(ComponentName name) {
             synchronized(mStartLock) {
                 mService = null;
@@ -1317,24 +1319,33 @@
 
         public void disconnect() {
             mContext.unbindService(this);
+
+            synchronized (mStartLock) {
+                mService = null;
+                // If this is the active connection, clear it
+                if (mServiceConnection == this) {
+                    mServiceConnection = null;
+                }
+
+            }
         }
 
         public <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
-            try {
-                synchronized (mStartLock) {
+            synchronized (mStartLock) {
+                try {
                     if (mService == null) {
                         Log.w(TAG, method + " failed: not connected to TTS engine");
                         return errorResult;
                     }
                     return action.run(mService);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, method + " failed", ex);
+                    if (reconnect) {
+                        disconnect();
+                        initTts();
+                    }
+                    return errorResult;
                 }
-            } catch (RemoteException ex) {
-                Log.e(TAG, method + " failed", ex);
-                if (reconnect) {
-                    disconnect();
-                    initTts();
-                }
-                return errorResult;
             }
         }
     }
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 83a70f3f..987062a 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -27,6 +27,7 @@
 import android.text.style.EasyEditSpan;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.LeadingMarginSpan;
+import android.text.style.LocaleSpan;
 import android.text.style.MetricAffectingSpan;
 import android.text.style.QuoteSpan;
 import android.text.style.RelativeSizeSpan;
@@ -587,6 +588,8 @@
     public static final int SUGGESTION_RANGE_SPAN = 21;
     /** @hide */
     public static final int EASY_EDIT_SPAN = 22;
+    /** @hide */
+    public static final int LOCALE_SPAN = 23;
 
     /**
      * Flatten a CharSequence and whatever styles can be copied across processes
@@ -754,6 +757,10 @@
                     readSpan(p, sp, new EasyEditSpan());
                     break;
 
+                case LOCALE_SPAN:
+                    readSpan(p, sp, new LocaleSpan(p));
+                    break;
+
                 default:
                     throw new RuntimeException("bogus span encoding " + kind);
                 }
diff --git a/core/java/android/text/style/LocaleSpan.java b/core/java/android/text/style/LocaleSpan.java
new file mode 100644
index 0000000..a12c42f
--- /dev/null
+++ b/core/java/android/text/style/LocaleSpan.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 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.text.style;
+
+import android.graphics.Paint;
+import android.os.Parcel;
+import android.text.ParcelableSpan;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import java.util.Locale;
+
+/**
+ * Changes the {@link Locale} of the text to which the span is attached.
+ */
+public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {
+    private final Locale mLocale;
+
+    /**
+     * Creates a LocaleSpan.
+     * @param locale The {@link Locale} of the text to which the span is
+     * attached.
+     */
+    public LocaleSpan(Locale locale) {
+        mLocale = locale;
+    }
+
+    public LocaleSpan(Parcel src) {
+        mLocale = new Locale(src.readString(), src.readString(), src.readString());
+    }
+
+    @Override
+    public int getSpanTypeId() {
+        return TextUtils.LOCALE_SPAN;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mLocale.getLanguage());
+        dest.writeString(mLocale.getCountry());
+        dest.writeString(mLocale.getVariant());
+    }
+
+    /**
+     * Returns the {@link Locale}.
+     *
+     * @return The {@link Locale} for this span.
+     */
+    public Locale getLocale() {
+        return mLocale;
+    }
+
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        apply(ds, mLocale);
+    }
+
+    @Override
+    public void updateMeasureState(TextPaint paint) {
+        apply(paint, mLocale);
+    }
+
+    private static void apply(Paint paint, Locale locale) {
+        paint.setTextLocale(locale);
+    }
+}
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 6288ce5..392d1f2 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.hardware.display.DisplayManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -165,7 +166,7 @@
         mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
         mLastFrameTimeNanos = Long.MIN_VALUE;
 
-        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+        Display d = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
         mFrameIntervalNanos = (long)(1000000000 / d.getRefreshRate());
 
         mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5409b38..6f8ca13 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -67,20 +67,16 @@
     private int mCachedAppHeightCompat;
 
     /**
-     * The default Display id.
+     * The default Display id, which is the id of the built-in primary display
+     * assuming there is one.
      */
     public static final int DEFAULT_DISPLAY = 0;
 
     /**
-     * Uninitialized display.
-     * @hide
-     */
-    public static final int NO_DISPLAY = -1;
-
-    /**
      * Internal method to create a display.
      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
-     * to get a display object for the default display.
+     * or {@link android.hardware.display.DisplayManager#getDisplay}
+     * to get a display object.
      *
      * @hide
      */
@@ -114,6 +110,31 @@
     }
 
     /**
+     * Gets the display's layer stack.
+     *
+     * Each display has its own independent layer stack upon which surfaces
+     * are placed to be managed by surface flinger.
+     *
+     * @return The layer stack number.
+     * @hide
+     */
+    public int getLayerStack() {
+        // Note: This is the current convention but there is no requirement that
+        // the display id and layer stack id be the same.
+        return mDisplayId;
+    }
+
+    /**
+     * Gets the compatibility info used by this display instance.
+     *
+     * @return The compatibility info holder, or null if none is required.
+     * @hide
+     */
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        return mCompatibilityInfo;
+    }
+
+    /**
      * Gets the size of the display, in pixels.
      * <p>
      * Note that this value should <em>not</em> be used for computing layouts,
@@ -361,5 +382,16 @@
             mLastCachedAppSizeUpdate = now;
         }
     }
+
+    // For debugging purposes
+    @Override
+    public String toString() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            return "Display id " + mDisplayId + ": " + mDisplayInfo
+                    + ", " + mTempMetrics;
+        }
+    }
 }
 
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index c65ce63..e38f245 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -223,4 +223,17 @@
             }
         }
     }
+
+    // For debugging purposes
+    @Override
+    public String toString() {
+        return "app " + appWidth + " x " + appHeight
+                + ", real " + logicalWidth + " x " + logicalHeight
+                + ", largest app " + largestNominalAppWidth + " x " + largestNominalAppHeight
+                + ", smallest app " + smallestNominalAppWidth + " x " + smallestNominalAppHeight
+                + ", " + refreshRate + " fps"
+                + ", rotation " + rotation
+                + ", density " + logicalDensityDpi
+                + ", " + physicalXDpi + " x " + physicalYDpi + " dpi";
+    }
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 188fede..f906e24 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1101,7 +1101,7 @@
                 attachInfo.mIgnoreDirtyState = true;
                 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
 
-                view.mPrivateFlags |= View.DRAWN;
+                view.mPrivateFlags |= View.PFLAG_DRAWN;
 
                 final int surfaceState = checkCurrent();
                 if (surfaceState != SURFACE_STATE_ERROR) {
@@ -1135,9 +1135,9 @@
                     callbacks.onHardwarePreDraw(canvas);
 
                     try {
-                        view.mRecreateDisplayList =
-                                (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
-                        view.mPrivateFlags &= ~View.INVALIDATED;
+                        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
+                                == View.PFLAG_INVALIDATED;
+                        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
 
                         long getDisplayListStartTime = 0;
                         if (mProfileEnabled) {
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index e93e480..c5d9255 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -59,8 +59,8 @@
      * @param requestedWidth The width the window wants to be.
      * @param requestedHeight The height the window wants to be.
      * @param viewVisibility Window root view's visibility.
-     * @param flags Request flags: {@link WindowManagerImpl#RELAYOUT_INSETS_PENDING},
-     * {@link WindowManagerImpl#RELAYOUT_DEFER_SURFACE_DESTROY}.
+     * @param flags Request flags: {@link WindowManagerGlobal#RELAYOUT_INSETS_PENDING},
+     * {@link WindowManagerGlobal#RELAYOUT_DEFER_SURFACE_DESTROY}.
      * @param outFrame Rect in which is placed the new position/size on
      * screen.
      * @param outContentInsets Rect in which is placed the offsets from
@@ -79,8 +79,8 @@
      * was last displayed.
      * @param outSurface Object in which is placed the new display surface.
      * 
-     * @return int Result flags: {@link WindowManagerImpl#RELAYOUT_SHOW_FOCUS},
-     * {@link WindowManagerImpl#RELAYOUT_FIRST_TIME}.
+     * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
+     * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
      */
     int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             int requestedWidth, int requestedHeight, int viewVisibility,
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 5f5d1f2..517b514 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -246,22 +246,9 @@
     native private static void nativeClassInit();
     static { nativeClassInit(); }
 
-    /** create a surface @hide */
-    public Surface(SurfaceSession s,
-            int pid, int displayId, int w, int h, int format, int flags)
-        throws OutOfResourcesException {
-        checkHeadless();
-
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
-        mCanvas = new CompatibleCanvas();
-        init(s,pid,null,displayId,w,h,format,flags);
-    }
-
     /** create a surface with a name @hide */
     public Surface(SurfaceSession s,
-            int pid, String name, int displayId, int w, int h, int format, int flags)
+            int pid, String name, int layerStack, int w, int h, int format, int flags)
         throws OutOfResourcesException {
         checkHeadless();
 
@@ -269,7 +256,7 @@
             mCreationStack = new Exception();
         }
         mCanvas = new CompatibleCanvas();
-        init(s,pid,name,displayId,w,h,format,flags);
+        init(s, pid, name, layerStack, w, h, format, flags);
         mName = name;
     }
 
@@ -470,7 +457,7 @@
     /** @hide */
     public native   void setWindowCrop(Rect crop);
     /** @hide */
-    public native   void setDisplayId(int displayId);
+    public native   void setLayerStack(int layerStack);
 
 
    
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index f4d40cb..fdf1c22 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -296,7 +296,7 @@
         }
         
         boolean opaque = true;
-        if ((mPrivateFlags & SKIP_DRAW) == 0) {
+        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
             // this view draws, remove it from the transparent region
             opaque = super.gatherTransparentRegion(region);
         } else if (region != null) {
@@ -320,7 +320,7 @@
     public void draw(Canvas canvas) {
         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
             // draw() is not called when SKIP_DRAW is set
-            if ((mPrivateFlags & SKIP_DRAW) == 0) {
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
                 // punch a whole in the view-hierarchy below us
                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
             }
@@ -332,7 +332,7 @@
     protected void dispatchDraw(Canvas canvas) {
         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
             // if SKIP_DRAW is cleared, draw() has already punched a hole
-            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                 // punch a whole in the view-hierarchy below us
                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
             }
@@ -480,10 +480,10 @@
                     relayoutResult = mSession.relayout(
                         mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
                             visible ? VISIBLE : GONE,
-                            WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY,
+                            WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
                             mWinFrame, mContentInsets,
                             mVisibleInsets, mConfiguration, mNewSurface);
-                    if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
+                    if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                         mReportDrawNeeded = true;
                     }
 
@@ -516,8 +516,8 @@
 
                     SurfaceHolder.Callback callbacks[] = null;
 
-                    final boolean surfaceChanged =
-                            (relayoutResult&WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED) != 0;
+                    final boolean surfaceChanged = (relayoutResult
+                            & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
                     if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
                         mSurfaceCreated = false;
                         if (mSurface.isValid()) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2f2c906..b1f5e9e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -39,6 +39,7 @@
 import android.graphics.Shader;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -1568,17 +1569,17 @@
 
     // for mPrivateFlags:
     /** {@hide} */
-    static final int WANTS_FOCUS                    = 0x00000001;
+    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
     /** {@hide} */
-    static final int FOCUSED                        = 0x00000002;
+    static final int PFLAG_FOCUSED                     = 0x00000002;
     /** {@hide} */
-    static final int SELECTED                       = 0x00000004;
+    static final int PFLAG_SELECTED                    = 0x00000004;
     /** {@hide} */
-    static final int IS_ROOT_NAMESPACE              = 0x00000008;
+    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
     /** {@hide} */
-    static final int HAS_BOUNDS                     = 0x00000010;
+    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
     /** {@hide} */
-    static final int DRAWN                          = 0x00000020;
+    static final int PFLAG_DRAWN                       = 0x00000020;
     /**
      * When this flag is set, this view is running an animation on behalf of its
      * children and should therefore not cancel invalidate requests, even if they
@@ -1586,58 +1587,58 @@
      *
      * {@hide}
      */
-    static final int DRAW_ANIMATION                 = 0x00000040;
+    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
     /** {@hide} */
-    static final int SKIP_DRAW                      = 0x00000080;
+    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
     /** {@hide} */
-    static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
+    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
     /** {@hide} */
-    static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
+    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
     /** {@hide} */
-    static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
+    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
     /** {@hide} */
-    static final int MEASURED_DIMENSION_SET         = 0x00000800;
+    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
     /** {@hide} */
-    static final int FORCE_LAYOUT                   = 0x00001000;
+    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
     /** {@hide} */
-    static final int LAYOUT_REQUIRED                = 0x00002000;
+    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
 
-    private static final int PRESSED                = 0x00004000;
+    private static final int PFLAG_PRESSED             = 0x00004000;
 
     /** {@hide} */
-    static final int DRAWING_CACHE_VALID            = 0x00008000;
+    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
     /**
      * Flag used to indicate that this view should be drawn once more (and only once
      * more) after its animation has completed.
      * {@hide}
      */
-    static final int ANIMATION_STARTED              = 0x00010000;
+    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
 
-    private static final int SAVE_STATE_CALLED      = 0x00020000;
+    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
 
     /**
      * Indicates that the View returned true when onSetAlpha() was called and that
      * the alpha must be restored.
      * {@hide}
      */
-    static final int ALPHA_SET                      = 0x00040000;
+    static final int PFLAG_ALPHA_SET                   = 0x00040000;
 
     /**
      * Set by {@link #setScrollContainer(boolean)}.
      */
-    static final int SCROLL_CONTAINER               = 0x00080000;
+    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
 
     /**
      * Set by {@link #setScrollContainer(boolean)}.
      */
-    static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
+    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
 
     /**
      * View flag indicating whether this view was invalidated (fully or partially.)
      *
      * @hide
      */
-    static final int DIRTY                          = 0x00200000;
+    static final int PFLAG_DIRTY                       = 0x00200000;
 
     /**
      * View flag indicating whether this view was invalidated by an opaque
@@ -1645,35 +1646,35 @@
      *
      * @hide
      */
-    static final int DIRTY_OPAQUE                   = 0x00400000;
+    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
 
     /**
-     * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
+     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
      *
      * @hide
      */
-    static final int DIRTY_MASK                     = 0x00600000;
+    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
 
     /**
      * Indicates whether the background is opaque.
      *
      * @hide
      */
-    static final int OPAQUE_BACKGROUND              = 0x00800000;
+    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
 
     /**
      * Indicates whether the scrollbars are opaque.
      *
      * @hide
      */
-    static final int OPAQUE_SCROLLBARS              = 0x01000000;
+    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
 
     /**
      * Indicates whether the view is opaque.
      *
      * @hide
      */
-    static final int OPAQUE_MASK                    = 0x01800000;
+    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
 
     /**
      * Indicates a prepressed state;
@@ -1683,27 +1684,27 @@
      *
      * @hide
      */
-    private static final int PREPRESSED             = 0x02000000;
+    private static final int PFLAG_PREPRESSED          = 0x02000000;
 
     /**
      * Indicates whether the view is temporarily detached.
      *
      * @hide
      */
-    static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
+    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
 
     /**
      * Indicates that we should awaken scroll bars once attached
      *
      * @hide
      */
-    private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
+    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
 
     /**
      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
      * @hide
      */
-    private static final int HOVERED              = 0x10000000;
+    private static final int PFLAG_HOVERED             = 0x10000000;
 
     /**
      * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
@@ -1711,10 +1712,10 @@
      *
      * @hide
      */
-    private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
+    private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
 
     /** {@hide} */
-    static final int ACTIVATED                    = 0x40000000;
+    static final int PFLAG_ACTIVATED                   = 0x40000000;
 
     /**
      * Indicates that this view was specifically invalidated, not just dirtied because some
@@ -1724,7 +1725,7 @@
      *
      * @hide
      */
-    static final int INVALIDATED                  = 0x80000000;
+    static final int PFLAG_INVALIDATED                 = 0x80000000;
 
     /* Masks for mPrivateFlags2 */
 
@@ -1733,7 +1734,7 @@
      * Cleared when the drag operation concludes.
      * @hide
      */
-    static final int DRAG_CAN_ACCEPT              = 0x00000001;
+    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
 
     /**
      * Indicates that this view is currently directly under the drag location in a
@@ -1741,7 +1742,7 @@
      * the drag exits the view, or when the drag operation concludes.
      * @hide
      */
-    static final int DRAG_HOVERED                 = 0x00000002;
+    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
 
     /**
      * Horizontal layout direction of this view is from Left to Right.
@@ -1771,32 +1772,33 @@
      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
      * @hide
      */
-    static final int LAYOUT_DIRECTION_MASK_SHIFT = 2;
+    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
 
     /**
      * Mask for use with private flags indicating bits used for horizontal layout direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_MASK = 0x00000003 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
      * right-to-left direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED_RTL = 4 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Indicates whether the view horizontal layout direction has been resolved.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED = 8 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
+            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
 
     /*
      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
@@ -1823,7 +1825,7 @@
      *
      * @hide
      */
-    static final int HAS_TRANSIENT_STATE = 0x00000100;
+    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x00000100;
 
 
     /**
@@ -1863,58 +1865,61 @@
     /**
      * Default text direction is inherited
      */
-    protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
+    public static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
 
     /**
      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
      * @hide
      */
-    static final int TEXT_DIRECTION_MASK_SHIFT = 6;
+    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
 
     /**
      * Mask for use with private flags indicating bits used for text direction.
      * @hide
      */
-    static final int TEXT_DIRECTION_MASK = 0x00000007 << TEXT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
+            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
 
     /**
      * Array of text direction flags for mapping attribute "textDirection" to correct
      * flag value.
      * @hide
      */
-    private static final int[] TEXT_DIRECTION_FLAGS = {
-            TEXT_DIRECTION_INHERIT << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_ANY_RTL << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_LTR << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_RTL << TEXT_DIRECTION_MASK_SHIFT,
-            TEXT_DIRECTION_LOCALE << TEXT_DIRECTION_MASK_SHIFT
+    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
+            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
+            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
     };
 
     /**
      * Indicates whether the view text direction has been resolved.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED = 0x00000008 << TEXT_DIRECTION_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
+            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
 
     /**
      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
 
     /**
      * Mask for use with private flags indicating bits used for resolved text direction.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
+            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
 
     /**
      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
      * @hide
      */
-    static final int TEXT_DIRECTION_RESOLVED_DEFAULT =
-            TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
+            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
 
     /*
      * Default text alignment. The text alignment of this View is inherited from its parent.
@@ -1970,58 +1975,59 @@
     /**
      * Default text alignment is inherited
      */
-    protected static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
+    public static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
 
     /**
       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
       * @hide
       */
-    static final int TEXT_ALIGNMENT_MASK_SHIFT = 13;
+    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
 
     /**
       * Mask for use with private flags indicating bits used for text alignment.
       * @hide
       */
-    static final int TEXT_ALIGNMENT_MASK = 0x00000007 << TEXT_ALIGNMENT_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
 
     /**
      * Array of text direction flags for mapping attribute "textAlignment" to correct
      * flag value.
      * @hide
      */
-    private static final int[] TEXT_ALIGNMENT_FLAGS = {
-            TEXT_ALIGNMENT_INHERIT << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_TEXT_START << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_TEXT_END << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_CENTER << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_VIEW_START << TEXT_ALIGNMENT_MASK_SHIFT,
-            TEXT_ALIGNMENT_VIEW_END << TEXT_ALIGNMENT_MASK_SHIFT
+    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
+            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
     };
 
     /**
      * Indicates whether the view text alignment has been resolved.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED = 0x00000008 << TEXT_ALIGNMENT_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
 
     /**
      * Bit shift to get the resolved text alignment.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
 
     /**
      * Mask for use with private flags indicating bits used for text alignment.
      * @hide
      */
-    static final int TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
+            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
 
     /**
      * Indicates whether if the view text alignment has been resolved to gravity
      */
-    public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT =
-            TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
+            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
 
     // Accessiblity constants for mPrivateFlags2
 
@@ -2029,7 +2035,7 @@
      * Shift for the bits in {@link #mPrivateFlags2} related to the
      * "importantForAccessibility" attribute.
      */
-    static final int IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
+    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
 
     /**
      * Automatically determine whether a view is important for accessibility.
@@ -2055,26 +2061,27 @@
      * Mask for obtainig the bits which specify how to determine
      * whether a view is important for accessibility.
      */
-    static final int IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
+    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
-        << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
 
     /**
      * Flag indicating whether a view has accessibility focus.
      */
-    static final int ACCESSIBILITY_FOCUSED = 0x00000040 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
 
     /**
      * Flag indicating whether a view state for accessibility has changed.
      */
-    static final int ACCESSIBILITY_STATE_CHANGED = 0x00000080 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+    static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
+            << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
 
     /**
      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
      * is used to check whether later changes to the view's transform should invalidate the
      * view to force the quickReject test to run again.
      */
-    static final int VIEW_QUICK_REJECTED = 0x10000000;
+    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
 
     /**
      * Flag indicating that start/end padding has been resolved into left/right padding
@@ -2083,7 +2090,7 @@
      * during measurement. In some special cases this is required such as when an adapter-based
      * view measures prospective children without attaching them to a window.
      */
-    static final int PADDING_RESOLVED = 0x20000000;
+    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
 
     // There are a couple of flags left in mPrivateFlags2
 
@@ -2096,19 +2103,19 @@
      * an animation is cleared between successive frames, in order to tell the associated
      * DisplayList to clear its animation matrix.
      */
-    static final int VIEW_IS_ANIMATING_TRANSFORM = 0x1;
+    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
 
     /**
      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
      * animation is cleared between successive frames, in order to tell the associated
      * DisplayList to restore its alpha value.
      */
-    static final int VIEW_IS_ANIMATING_ALPHA = 0x2;
+    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
 
 
     /* End of masks for mPrivateFlags3 */
 
-    static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
+    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
 
     /**
      * Always allow a user to over-scroll this view, provided it is a
@@ -2475,16 +2482,16 @@
      * {@hide}
      */
     @ViewDebug.ExportedProperty(flagMapping = {
-        @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
+        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
                 name = "FORCE_LAYOUT"),
-        @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
+        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
                 name = "LAYOUT_REQUIRED"),
-        @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
             name = "DRAWING_CACHE_INVALID", outputIf = false),
-        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
-        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
-        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
-        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
+        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
+        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
+        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
     })
     int mPrivateFlags;
     int mPrivateFlags2;
@@ -3100,6 +3107,19 @@
      */
     private boolean mSendingHoverAccessibilityEvents;
 
+    /**
+     * Delegate for injecting accessiblity functionality.
+     */
+    AccessibilityDelegate mAccessibilityDelegate;
+
+    /**
+     * Consistency verifier for debugging purposes.
+     * @hide
+     */
+    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
+            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
+                    new InputEventConsistencyVerifier(this, 0) : null;
+
     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
 
     /**
@@ -3113,10 +3133,10 @@
         mResources = context != null ? context.getResources() : null;
         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
         // Set layout and text direction defaults
-        mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
-                (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
-                (TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT) |
-                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
+        mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
+                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
+                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
+                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
         mUserPaddingStart = UNDEFINED_PADDING;
@@ -3124,19 +3144,6 @@
     }
 
     /**
-     * Delegate for injecting accessiblity functionality.
-     */
-    AccessibilityDelegate mAccessibilityDelegate;
-
-    /**
-     * Consistency verifier for debugging purposes.
-     * @hide
-     */
-    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
-            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
-                    new InputEventConsistencyVerifier(this, 0) : null;
-
-    /**
      * Constructor that is called when inflating a view from XML. This is called
      * when a view is being constructed from an XML file, supplying attributes
      * that were specified in the XML file. This version uses a default style of
@@ -3346,12 +3353,12 @@
                     break;
                 case com.android.internal.R.styleable.View_layoutDirection:
                     // Clear any layout direction flags (included resolved bits) already set
-                    mPrivateFlags2 &= ~(LAYOUT_DIRECTION_MASK | LAYOUT_DIRECTION_RESOLVED_MASK);
+                    mPrivateFlags2 &= ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
                     // Set the layout direction flags depending on the value of the attribute
                     final int layoutDirection = a.getInt(attr, -1);
                     final int value = (layoutDirection != -1) ?
                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
-                    mPrivateFlags2 |= (value << LAYOUT_DIRECTION_MASK_SHIFT);
+                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
                     break;
                 case com.android.internal.R.styleable.View_drawingCacheQuality:
                     final int cacheQuality = a.getInt(attr, 0);
@@ -3496,19 +3503,19 @@
                     break;
                 case R.styleable.View_textDirection:
                     // Clear any text direction flag already set
-                    mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
+                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
                     // Set the text direction flags depending on the value of the attribute
                     final int textDirection = a.getInt(attr, -1);
                     if (textDirection != -1) {
-                        mPrivateFlags2 |= TEXT_DIRECTION_FLAGS[textDirection];
+                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
                     }
                     break;
                 case R.styleable.View_textAlignment:
                     // Clear any text alignment flag already set
-                    mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
                     // Set the text alignment flag depending on the value of the attribute
                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
-                    mPrivateFlags2 |= TEXT_ALIGNMENT_FLAGS[textAlignment];
+                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
                     break;
                 case R.styleable.View_importantForAccessibility:
                     setImportantForAccessibility(a.getInt(attr,
@@ -3588,6 +3595,81 @@
         mResources = null;
     }
 
+    public String toString() {
+        StringBuilder out = new StringBuilder(128);
+        out.append(getClass().getName());
+        out.append('{');
+        out.append(Integer.toHexString(System.identityHashCode(this)));
+        out.append(' ');
+        switch (mViewFlags&VISIBILITY_MASK) {
+            case VISIBLE: out.append('V'); break;
+            case INVISIBLE: out.append('I'); break;
+            case GONE: out.append('G'); break;
+            default: out.append('.'); break;
+        }
+        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
+        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
+        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
+        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
+        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
+        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
+        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
+        out.append(' ');
+        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
+        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
+        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
+        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
+            out.append('p');
+        } else {
+            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
+        }
+        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
+        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
+        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
+        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
+        out.append(' ');
+        out.append(mLeft);
+        out.append(',');
+        out.append(mTop);
+        out.append('-');
+        out.append(mRight);
+        out.append(',');
+        out.append(mBottom);
+        final int id = getId();
+        if (id != NO_ID) {
+            out.append(" #");
+            out.append(Integer.toHexString(id));
+            final Resources r = mResources;
+            if (id != 0 && r != null) {
+                try {
+                    String pkgname;
+                    switch (id&0xff000000) {
+                        case 0x7f000000:
+                            pkgname="app";
+                            break;
+                        case 0x01000000:
+                            pkgname="android";
+                            break;
+                        default:
+                            pkgname = r.getResourcePackageName(id);
+                            break;
+                    }
+                    String typename = r.getResourceTypeName(id);
+                    String entryname = r.getResourceEntryName(id);
+                    out.append(" ");
+                    out.append(pkgname);
+                    out.append(":");
+                    out.append(typename);
+                    out.append("/");
+                    out.append(entryname);
+                } catch (Resources.NotFoundException e) {
+                }
+            }
+        }
+        out.append("}");
+        return out.toString();
+    }
+
     /**
      * <p>
      * Initializes the fading edges from a given set of styled attributes. This
@@ -4145,8 +4227,8 @@
             System.out.println(this + " requestFocus()");
         }
 
-        if ((mPrivateFlags & FOCUSED) == 0) {
-            mPrivateFlags |= FOCUSED;
+        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
+            mPrivateFlags |= PFLAG_FOCUSED;
 
             if (mParent != null) {
                 mParent.requestChildFocus(this, this);
@@ -4230,8 +4312,8 @@
             System.out.println(this + " clearFocus()");
         }
 
-        if ((mPrivateFlags & FOCUSED) != 0) {
-            mPrivateFlags &= ~FOCUSED;
+        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+            mPrivateFlags &= ~PFLAG_FOCUSED;
 
             if (mParent != null) {
                 mParent.clearChildFocus(this);
@@ -4265,8 +4347,8 @@
             System.out.println(this + " unFocus()");
         }
 
-        if ((mPrivateFlags & FOCUSED) != 0) {
-            mPrivateFlags &= ~FOCUSED;
+        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+            mPrivateFlags &= ~PFLAG_FOCUSED;
 
             onFocusChanged(false, 0, null);
             refreshDrawableState();
@@ -4285,7 +4367,7 @@
      */
     @ViewDebug.ExportedProperty(category = "focus")
     public boolean hasFocus() {
-        return (mPrivateFlags & FOCUSED) != 0;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
     }
 
     /**
@@ -4985,7 +5067,7 @@
      */
     @ViewDebug.ExportedProperty(category = "focus")
     public boolean isFocused() {
-        return (mPrivateFlags & FOCUSED) != 0;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
     }
 
     /**
@@ -4996,7 +5078,7 @@
      *         be found.
      */
     public View findFocus() {
-        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
     }
 
     /**
@@ -5009,7 +5091,7 @@
      * @attr ref android.R.styleable#View_isScrollContainer
      */
     public boolean isScrollContainer() {
-        return (mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0;
+        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
     }
 
     /**
@@ -5023,16 +5105,16 @@
      */
     public void setScrollContainer(boolean isScrollContainer) {
         if (isScrollContainer) {
-            if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
+            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
                 mAttachInfo.mScrollContainers.add(this);
-                mPrivateFlags |= SCROLL_CONTAINER_ADDED;
+                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
             }
-            mPrivateFlags |= SCROLL_CONTAINER;
+            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
         } else {
-            if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
+            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
                 mAttachInfo.mScrollContainers.remove(this);
             }
-            mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
+            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
         }
     }
 
@@ -5539,7 +5621,7 @@
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
     })
     public int getLayoutDirection() {
-        return (mPrivateFlags2 & LAYOUT_DIRECTION_MASK) >> LAYOUT_DIRECTION_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
     }
 
     /**
@@ -5557,13 +5639,13 @@
     public void setLayoutDirection(int layoutDirection) {
         if (getLayoutDirection() != layoutDirection) {
             // Reset the current layout direction and the resolved one
-            mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK;
+            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
             resetResolvedLayoutDirection();
             // Reset padding resolution
-            mPrivateFlags2 &= ~PADDING_RESOLVED;
+            mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
             // Set the new layout direction (filtered)
             mPrivateFlags2 |=
-                    ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
+                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
             resolveRtlProperties();
             // ... and ask for a layout pass
             requestLayout();
@@ -5583,14 +5665,14 @@
     public int getResolvedLayoutDirection() {
         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
         if (targetSdkVersion < JELLY_BEAN_MR1) {
-            mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
+            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
             return LAYOUT_DIRECTION_LTR;
         }
         // The layout direction will be resolved only if needed
-        if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
+        if ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) != PFLAG2_LAYOUT_DIRECTION_RESOLVED) {
             resolveLayoutDirection();
         }
-        return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
+        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ?
                 LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
     }
 
@@ -5619,7 +5701,7 @@
      */
     @ViewDebug.ExportedProperty(category = "layout")
     public boolean hasTransientState() {
-        return (mPrivateFlags2 & HAS_TRANSIENT_STATE) == HAS_TRANSIENT_STATE;
+        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
     }
 
     /**
@@ -5646,8 +5728,8 @@
         if ((hasTransientState && mTransientStateCount == 1) ||
                 (!hasTransientState && mTransientStateCount == 0)) {
             // update flag if we've just incremented up from 0 or decremented down to 0
-            mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) |
-                    (hasTransientState ? HAS_TRANSIENT_STATE : 0);
+            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
+                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
             if (mParent != null) {
                 try {
                     mParent.childHasTransientStateChanged(this, hasTransientState);
@@ -5770,12 +5852,12 @@
      *        the View's internal state from a previously set "pressed" state.
      */
     public void setPressed(boolean pressed) {
-        final boolean needsRefresh = pressed != ((mPrivateFlags & PRESSED) == PRESSED);
+        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
 
         if (pressed) {
-            mPrivateFlags |= PRESSED;
+            mPrivateFlags |= PFLAG_PRESSED;
         } else {
-            mPrivateFlags &= ~PRESSED;
+            mPrivateFlags &= ~PFLAG_PRESSED;
         }
 
         if (needsRefresh) {
@@ -5806,7 +5888,7 @@
      * @return true if the view is currently pressed, false otherwise
      */
     public boolean isPressed() {
-        return (mPrivateFlags & PRESSED) == PRESSED;
+        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
     }
 
     /**
@@ -6133,7 +6215,7 @@
      * @return True if this View is accessibility focused.
      */
     boolean isAccessibilityFocused() {
-        return (mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0;
+        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
     }
 
     /**
@@ -6158,8 +6240,8 @@
         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
             return false;
         }
-        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) == 0) {
-            mPrivateFlags2 |= ACCESSIBILITY_FOCUSED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
+            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
             ViewRootImpl viewRootImpl = getViewRootImpl();
             if (viewRootImpl != null) {
                 viewRootImpl.setAccessibilityFocus(this, null);
@@ -6181,8 +6263,8 @@
      * @hide
      */
     public void clearAccessibilityFocus() {
-        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
-            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
+            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
             invalidate();
             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
             notifyAccessibilityStateChanged();
@@ -6230,8 +6312,8 @@
      * another view.
      */
     void clearAccessibilityFocusNoCallbacks() {
-        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
-            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
+            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
             invalidate();
         }
     }
@@ -6388,8 +6470,8 @@
             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
         })
     public int getImportantForAccessibility() {
-        return (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
-                >> IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
+                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
     }
 
     /**
@@ -6407,9 +6489,9 @@
      */
     public void setImportantForAccessibility(int mode) {
         if (mode != getImportantForAccessibility()) {
-            mPrivateFlags2 &= ~IMPORTANT_FOR_ACCESSIBILITY_MASK;
-            mPrivateFlags2 |= (mode << IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
-                    & IMPORTANT_FOR_ACCESSIBILITY_MASK;
+            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
+            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
+                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
             notifyAccessibilityStateChanged();
         }
     }
@@ -6422,8 +6504,8 @@
      * @hide
      */
     public boolean isImportantForAccessibility() {
-        final int mode = (mPrivateFlags2 & IMPORTANT_FOR_ACCESSIBILITY_MASK)
-                >> IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
+                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
         switch (mode) {
             case IMPORTANT_FOR_ACCESSIBILITY_YES:
                 return true;
@@ -6532,8 +6614,8 @@
         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
             return;
         }
-        if ((mPrivateFlags2 & ACCESSIBILITY_STATE_CHANGED) == 0) {
-            mPrivateFlags2 |= ACCESSIBILITY_STATE_CHANGED;
+        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
+            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
             if (mParent != null) {
                 mParent.childAccessibilityStateChanged(this);
             }
@@ -6547,7 +6629,7 @@
      * @hide
      */
     public void resetAccessibilityStateChanged() {
-        mPrivateFlags2 &= ~ACCESSIBILITY_STATE_CHANGED;
+        mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
     }
 
     /**
@@ -6799,7 +6881,7 @@
      */
     public void onStartTemporaryDetach() {
         removeUnsetPressCallback();
-        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
+        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
     }
 
     /**
@@ -7118,13 +7200,13 @@
             if (isPressed()) {
                 setPressed(false);
             }
-            if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
+            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
                 imm.focusOut(this);
             }
             removeLongPressCallback();
             removeTapCallback();
             onFocusLost();
-        } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
+        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
             imm.focusIn(this);
         }
         refreshDrawableState();
@@ -7164,7 +7246,7 @@
             if (mAttachInfo != null) {
                 initialAwakenScrollBars();
             } else {
-                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
+                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
             }
         }
     }
@@ -7265,7 +7347,7 @@
             outRect.bottom -= insets.bottom;
             return;
         }
-        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+        Display d = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
         d.getRectSize(outRect);
     }
 
@@ -7764,7 +7846,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isHovered() {
-        return (mPrivateFlags & HOVERED) != 0;
+        return (mPrivateFlags & PFLAG_HOVERED) != 0;
     }
 
     /**
@@ -7784,14 +7866,14 @@
      */
     public void setHovered(boolean hovered) {
         if (hovered) {
-            if ((mPrivateFlags & HOVERED) == 0) {
-                mPrivateFlags |= HOVERED;
+            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
+                mPrivateFlags |= PFLAG_HOVERED;
                 refreshDrawableState();
                 onHoverChanged(true);
             }
         } else {
-            if ((mPrivateFlags & HOVERED) != 0) {
-                mPrivateFlags &= ~HOVERED;
+            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
+                mPrivateFlags &= ~PFLAG_HOVERED;
                 refreshDrawableState();
                 onHoverChanged(false);
             }
@@ -7823,7 +7905,7 @@
         final int viewFlags = mViewFlags;
 
         if ((viewFlags & ENABLED_MASK) == DISABLED) {
-            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
+            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                 setPressed(false);
             }
             // A disabled view that is clickable still consumes the touch
@@ -7842,8 +7924,8 @@
                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
             switch (event.getAction()) {
                 case MotionEvent.ACTION_UP:
-                    boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
-                    if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
+                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
+                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
                         // take focus if we don't have it already and we should in
                         // touch mode.
                         boolean focusTaken = false;
@@ -7905,7 +7987,7 @@
                     // For views inside a scrolling container, delay the pressed feedback for
                     // a short period in case this is a scroll.
                     if (isInScrollingContainer) {
-                        mPrivateFlags |= PREPRESSED;
+                        mPrivateFlags |= PFLAG_PREPRESSED;
                         if (mPendingCheckForTap == null) {
                             mPendingCheckForTap = new CheckForTap();
                         }
@@ -7930,7 +8012,7 @@
                     if (!pointInView(x, y, mTouchSlop)) {
                         // Outside button
                         removeTapCallback();
-                        if ((mPrivateFlags & PRESSED) != 0) {
+                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
                             // Remove any future long press/tap checks
                             removeLongPressCallback();
 
@@ -7981,7 +8063,7 @@
      * Remove the prepress detection timer.
      */
     private void removeUnsetPressCallback() {
-        if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
+        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
             setPressed(false);
             removeCallbacks(mUnsetPressedState);
         }
@@ -7992,7 +8074,7 @@
      */
     private void removeTapCallback() {
         if (mPendingCheckForTap != null) {
-            mPrivateFlags &= ~PREPRESSED;
+            mPrivateFlags &= ~PFLAG_PREPRESSED;
             removeCallbacks(mPendingCheckForTap);
         }
     }
@@ -8057,13 +8139,13 @@
 
         /* Check if the FOCUSABLE bit has changed */
         if (((changed & FOCUSABLE_MASK) != 0) &&
-                ((privateFlags & HAS_BOUNDS) !=0)) {
+                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
-                    && ((privateFlags & FOCUSED) != 0)) {
+                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
                 /* Give up focus if we are no longer focusable */
                 clearFocus();
             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
-                    && ((privateFlags & FOCUSED) == 0)) {
+                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
                 /*
                  * Tell the view system that we are now available to take focus
                  * if no one else already has it.
@@ -8082,7 +8164,7 @@
                  * it was not visible. Marking it drawn ensures that the invalidation will
                  * go through.
                  */
-                mPrivateFlags |= DRAWN;
+                mPrivateFlags |= PFLAG_DRAWN;
                 invalidate(true);
 
                 needGlobalAttributesUpdate(true);
@@ -8112,7 +8194,7 @@
                 }
                 // Mark the view drawn to ensure that it gets invalidated properly the next
                 // time it is visible and gets invalidated
-                mPrivateFlags |= DRAWN;
+                mPrivateFlags |= PFLAG_DRAWN;
             }
             if (mAttachInfo != null) {
                 mAttachInfo.mViewVisibilityChanged = true;
@@ -8126,7 +8208,7 @@
              * If this view is becoming invisible, set the DRAWN flag so that
              * the next invalidate() will not be skipped.
              */
-            mPrivateFlags |= DRAWN;
+            mPrivateFlags |= PFLAG_DRAWN;
 
             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
                 // root view becoming invisible shouldn't clear focus and accessibility focus
@@ -8157,25 +8239,25 @@
 
         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
             destroyDrawingCache();
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
             invalidateParentCaches();
         }
 
         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
             destroyDrawingCache();
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
         }
 
         if ((changed & DRAW_MASK) != 0) {
             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
                 if (mBackground != null) {
-                    mPrivateFlags &= ~SKIP_DRAW;
-                    mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
+                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
+                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
                 } else {
-                    mPrivateFlags |= SKIP_DRAW;
+                    mPrivateFlags |= PFLAG_SKIP_DRAW;
                 }
             } else {
-                mPrivateFlags &= ~SKIP_DRAW;
+                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
             }
             requestLayout();
             invalidate(true);
@@ -8483,7 +8565,7 @@
             // asked for the matrix; recalculate it with the current values
 
             // Figure out if we need to update the pivot point
-            if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+            if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
                     info.mPrevWidth = mRight - mLeft;
                     info.mPrevHeight = mBottom - mTop;
@@ -8627,7 +8709,7 @@
         if (mDisplayList != null) {
             mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
         }
-        if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
             // View was rejected last time it was drawn by its parent; this may have changed
             invalidateParentIfNeeded();
         }
@@ -8673,7 +8755,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setRotation(rotation);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -8724,7 +8806,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setRotationY(rotationY);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -8775,7 +8857,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setRotationX(rotationX);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -8818,7 +8900,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setScaleX(scaleX);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -8861,7 +8943,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setScaleY(scaleY);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -8902,7 +8984,7 @@
      */
     public void setPivotX(float pivotX) {
         ensureTransformationInfo();
-        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
+        mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
         final TransformationInfo info = mTransformationInfo;
         if (info.mPivotX != pivotX) {
             invalidateViewProperty(true, false);
@@ -8912,7 +8994,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setPivotX(pivotX);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -8952,7 +9034,7 @@
      */
     public void setPivotY(float pivotY) {
         ensureTransformationInfo();
-        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
+        mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
         final TransformationInfo info = mTransformationInfo;
         if (info.mPivotY != pivotY) {
             invalidateViewProperty(true, false);
@@ -8962,7 +9044,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setPivotY(pivotY);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9022,12 +9104,12 @@
         if (mTransformationInfo.mAlpha != alpha) {
             mTransformationInfo.mAlpha = alpha;
             if (onSetAlpha((int) (alpha * 255))) {
-                mPrivateFlags |= ALPHA_SET;
+                mPrivateFlags |= PFLAG_ALPHA_SET;
                 // subclass is handling alpha - don't optimize rendering cache invalidation
                 invalidateParentCaches();
                 invalidate(true);
             } else {
-                mPrivateFlags &= ~ALPHA_SET;
+                mPrivateFlags &= ~PFLAG_ALPHA_SET;
                 invalidateViewProperty(true, false);
                 if (mDisplayList != null) {
                     mDisplayList.setAlpha(alpha);
@@ -9052,10 +9134,10 @@
             mTransformationInfo.mAlpha = alpha;
             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
             if (subclassHandlesAlpha) {
-                mPrivateFlags |= ALPHA_SET;
+                mPrivateFlags |= PFLAG_ALPHA_SET;
                 return true;
             } else {
-                mPrivateFlags &= ~ALPHA_SET;
+                mPrivateFlags &= ~PFLAG_ALPHA_SET;
                 if (mDisplayList != null) {
                     mDisplayList.setAlpha(alpha);
                 }
@@ -9115,16 +9197,16 @@
             onSizeChanged(width, mBottom - mTop, width, oldHeight);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mTransformationInfo.mMatrixDirty = true;
                 }
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
             invalidateParentIfNeeded();
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9147,7 +9229,7 @@
      * @return The dirty state of this view.
      */
     public boolean isDirty() {
-        return (mPrivateFlags & DIRTY_MASK) != 0;
+        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
     }
 
     /**
@@ -9188,16 +9270,16 @@
             onSizeChanged(width, mBottom - mTop, width, oldHeight);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mTransformationInfo.mMatrixDirty = true;
                 }
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
             invalidateParentIfNeeded();
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9255,16 +9337,16 @@
             onSizeChanged(mRight - mLeft, height, oldWidth, height);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mTransformationInfo.mMatrixDirty = true;
                 }
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
             invalidateParentIfNeeded();
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9319,16 +9401,16 @@
             onSizeChanged(mRight - mLeft, height, oldWidth, height);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     mTransformationInfo.mMatrixDirty = true;
                 }
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
             invalidateParentIfNeeded();
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9416,7 +9498,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setTranslationX(translationX);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9457,7 +9539,7 @@
             if (mDisplayList != null) {
                 mDisplayList.setTranslationY(translationY);
             }
-            if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
                 invalidateParentIfNeeded();
             }
@@ -9928,12 +10010,12 @@
         if (skipInvalidate()) {
             return;
         }
-        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
-                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
-            mPrivateFlags |= INVALIDATED;
-            mPrivateFlags |= DIRTY;
+        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
+                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+            mPrivateFlags |= PFLAG_INVALIDATED;
+            mPrivateFlags |= PFLAG_DIRTY;
             final ViewParent p = mParent;
             final AttachInfo ai = mAttachInfo;
             //noinspection PointlessBooleanExpression,ConstantConditions
@@ -9971,12 +10053,12 @@
         if (skipInvalidate()) {
             return;
         }
-        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
-                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
-            mPrivateFlags |= INVALIDATED;
-            mPrivateFlags |= DIRTY;
+        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
+                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+            mPrivateFlags |= PFLAG_INVALIDATED;
+            mPrivateFlags |= PFLAG_DIRTY;
             final ViewParent p = mParent;
             final AttachInfo ai = mAttachInfo;
             //noinspection PointlessBooleanExpression,ConstantConditions
@@ -10023,15 +10105,15 @@
         if (skipInvalidate()) {
             return;
         }
-        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
-                (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
-                (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
+        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
+                (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
+                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
             mLastIsOpaque = isOpaque();
-            mPrivateFlags &= ~DRAWN;
-            mPrivateFlags |= DIRTY;
+            mPrivateFlags &= ~PFLAG_DRAWN;
+            mPrivateFlags |= PFLAG_DIRTY;
             if (invalidateCache) {
-                mPrivateFlags |= INVALIDATED;
-                mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                mPrivateFlags |= PFLAG_INVALIDATED;
+                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
             }
             final AttachInfo ai = mAttachInfo;
             final ViewParent p = mParent;
@@ -10072,12 +10154,12 @@
      * list properties are not being used in this view
      */
     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
-        if (mDisplayList == null || (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
+        if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
             if (invalidateParent) {
                 invalidateParentCaches();
             }
             if (forceRedraw) {
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
             }
             invalidate(false);
         } else {
@@ -10121,7 +10203,7 @@
      */
     protected void invalidateParentCaches() {
         if (mParent instanceof View) {
-            ((View) mParent).mPrivateFlags |= INVALIDATED;
+            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
         }
     }
 
@@ -10153,7 +10235,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public boolean isOpaque() {
-        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
+        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
                 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
     }
 
@@ -10167,17 +10249,17 @@
         //   - Doesn't have scrollbars or scrollbars are inside overlay
 
         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
-            mPrivateFlags |= OPAQUE_BACKGROUND;
+            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
         } else {
-            mPrivateFlags &= ~OPAQUE_BACKGROUND;
+            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
         }
 
         final int flags = mViewFlags;
         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
-            mPrivateFlags |= OPAQUE_SCROLLBARS;
+            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
         } else {
-            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
+            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
         }
     }
 
@@ -10185,7 +10267,7 @@
      * @hide
      */
     protected boolean hasOpaqueScrollbars() {
-        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
+        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
     }
 
     /**
@@ -11230,13 +11312,13 @@
      * @see #onDetachedFromWindow()
      */
     protected void onAttachedToWindow() {
-        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
+        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
             mParent.requestTransparentRegion(this);
         }
 
-        if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
+        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
             initialAwakenScrollBars();
-            mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
+            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
         }
 
         jumpDrawablesToCurrentState();
@@ -11297,7 +11379,7 @@
      */
     public void resolveLayoutDirection() {
         // Clear any previous layout direction resolution
-        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
+        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
 
         if (hasRtlSupport()) {
             // Set resolved depending on layout direction
@@ -11314,15 +11396,15 @@
                     if (!viewGroup.canResolveLayoutDirection()) return;
 
                     if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
                     break;
                 case LAYOUT_DIRECTION_RTL:
-                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                     break;
                 case LAYOUT_DIRECTION_LOCALE:
                     if(isLayoutDirectionRtl(Locale.getDefault())) {
-                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
                     break;
                 default:
@@ -11331,7 +11413,7 @@
         }
 
         // Set to resolved
-        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
+        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
         onResolvedLayoutDirectionChanged();
     }
 
@@ -11347,7 +11429,7 @@
      * Return if padding has been resolved
      */
     boolean isPaddingResolved() {
-        return (mPrivateFlags2 & PADDING_RESOLVED) != 0;
+        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) != 0;
     }
 
     /**
@@ -11403,7 +11485,7 @@
             onPaddingChanged(resolvedLayoutDirection);
         }
 
-        mPrivateFlags2 |= PADDING_RESOLVED;
+        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
     }
 
     /**
@@ -11439,7 +11521,7 @@
      */
     public void resetResolvedLayoutDirection() {
         // Reset the current resolved bits
-        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
+        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
         onResolvedLayoutDirectionReset();
         // Reset also the text direction
         resetResolvedTextDirection();
@@ -11473,7 +11555,7 @@
      * @see #onAttachedToWindow()
      */
     protected void onDetachedFromWindow() {
-        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
 
         removeUnsetPressCallback();
         removeLongPressCallback();
@@ -11499,7 +11581,7 @@
         resetResolvedLayoutDirection();
         resetResolvedTextAlignment();
         resetAccessibilityStateChanged();
-        mPrivateFlags2 &= ~PADDING_RESOLVED;
+        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
     }
 
     /**
@@ -11541,6 +11623,15 @@
     }
 
     /**
+     * Gets the logical display to which the view's window has been attached.
+     *
+     * @return The logical display, or null if the view is not currently attached to a window.
+     */
+    public Display getDisplay() {
+        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
+    }
+
+    /**
      * Retrieve private session object this view hierarchy is using to
      * communicate with the window manager.
      * @return the session object to communicate with the window manager
@@ -11558,14 +11649,14 @@
         mAttachInfo = info;
         mWindowAttachCount++;
         // We will need to evaluate the drawable state at least once.
-        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
+        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
         if (mFloatingTreeObserver != null) {
             info.mTreeObserver.merge(mFloatingTreeObserver);
             mFloatingTreeObserver = null;
         }
-        if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
+        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
             mAttachInfo.mScrollContainers.add(this);
-            mPrivateFlags |= SCROLL_CONTAINER_ADDED;
+            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
         }
         performCollectViewAttributes(mAttachInfo, visibility);
         onAttachedToWindow();
@@ -11587,7 +11678,7 @@
         if (vis != GONE) {
             onWindowVisibilityChanged(vis);
         }
-        if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
+        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
             // If nobody has evaluated the drawable state yet, then do it now.
             refreshDrawableState();
         }
@@ -11617,9 +11708,9 @@
             }
         }
 
-        if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
+        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
             mAttachInfo.mScrollContainers.remove(this);
-            mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
+            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
         }
 
         mAttachInfo = null;
@@ -11651,9 +11742,9 @@
      */
     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
-            mPrivateFlags &= ~SAVE_STATE_CALLED;
+            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
             Parcelable state = onSaveInstanceState();
-            if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
+            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                 throw new IllegalStateException(
                         "Derived class did not call super.onSaveInstanceState()");
             }
@@ -11687,7 +11778,7 @@
      * @see #setSaveEnabled(boolean)
      */
     protected Parcelable onSaveInstanceState() {
-        mPrivateFlags |= SAVE_STATE_CALLED;
+        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
         return BaseSavedState.EMPTY_STATE;
     }
 
@@ -11722,9 +11813,9 @@
             if (state != null) {
                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
                 // + ": " + state);
-                mPrivateFlags &= ~SAVE_STATE_CALLED;
+                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
                 onRestoreInstanceState(state);
-                if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
+                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                     throw new IllegalStateException(
                             "Derived class did not call super.onRestoreInstanceState()");
                 }
@@ -11745,7 +11836,7 @@
      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
      */
     protected void onRestoreInstanceState(Parcelable state) {
-        mPrivateFlags |= SAVE_STATE_CALLED;
+        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
         if (state != BaseSavedState.EMPTY_STATE && state != null) {
             throw new IllegalArgumentException("Wrong state class, expecting View State but "
                     + "received " + state.getClass().toString() + " instead. This usually happens "
@@ -11960,7 +12051,7 @@
             return null;
         }
 
-        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
+        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
             if (mHardwareLayer == null) {
                 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
                         width, height, isOpaque());
@@ -12090,10 +12181,10 @@
      */
     @SuppressWarnings({"UnusedDeclaration"})
     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
-        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
-                ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
-                (mPrivateFlags & View.DRAWING_CACHE_VALID) +
-                ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
+        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
+                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
+                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
+                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
         if (clear) {
             mPrivateFlags &= clearMask;
         }
@@ -12157,15 +12248,15 @@
             return null;
         }
 
-        if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
+        if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
                 displayList == null || !displayList.isValid() ||
                 (!isLayer && mRecreateDisplayList))) {
             // Don't need to recreate the display list, just need to tell our
             // children to restore/recreate theirs
             if (displayList != null && displayList.isValid() &&
                     !isLayer && !mRecreateDisplayList) {
-                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-                mPrivateFlags &= ~DIRTY_MASK;
+                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                 dispatchGetDisplayList();
 
                 return displayList;
@@ -12220,12 +12311,12 @@
 
                     canvas.translate(-mScrollX, -mScrollY);
                     if (!isLayer) {
-                        mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-                        mPrivateFlags &= ~DIRTY_MASK;
+                        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                     }
 
                     // Fast path for layouts with no backgrounds
-                    if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                         dispatchDraw(canvas);
                     } else {
                         draw(canvas);
@@ -12243,8 +12334,8 @@
                 }
             }
         } else if (!isLayer) {
-            mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-            mPrivateFlags &= ~DIRTY_MASK;
+            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
         }
 
         return displayList;
@@ -12366,7 +12457,7 @@
     public void setDrawingCacheBackgroundColor(int color) {
         if (color != mDrawingCacheBackgroundColor) {
             mDrawingCacheBackgroundColor = color;
-            mPrivateFlags &= ~DRAWING_CACHE_VALID;
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
         }
     }
 
@@ -12412,7 +12503,7 @@
      * @see #destroyDrawingCache()
      */
     public void buildDrawingCache(boolean autoScale) {
-        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
+        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
             mCachingFailed = false;
 
@@ -12528,15 +12619,15 @@
 
             canvas.translate(-mScrollX, -mScrollY);
 
-            mPrivateFlags |= DRAWN;
+            mPrivateFlags |= PFLAG_DRAWN;
             if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
                     mLayerType != LAYER_TYPE_NONE) {
-                mPrivateFlags |= DRAWING_CACHE_VALID;
+                mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
             }
 
             // Fast path for layouts with no backgrounds
-            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                mPrivateFlags &= ~DIRTY_MASK;
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
+                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                 dispatchDraw(canvas);
             } else {
                 draw(canvas);
@@ -12604,10 +12695,10 @@
 
         // Temporarily remove the dirty mask
         int flags = mPrivateFlags;
-        mPrivateFlags &= ~DIRTY_MASK;
+        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
 
         // Fast path for layouts with no backgrounds
-        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
             dispatchDraw(canvas);
         } else {
             draw(canvas);
@@ -12797,7 +12888,7 @@
                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
                     // The child need to draw an animation, potentially offscreen, so
                     // make sure we do not cancel invalidate requests
-                    parent.mPrivateFlags |= DRAW_ANIMATION;
+                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
                     parent.invalidate(mLeft, mTop, mRight, mBottom);
                 }
             } else {
@@ -12810,7 +12901,7 @@
 
                 // The child need to draw an animation, potentially offscreen, so
                 // make sure we do not cancel invalidate requests
-                parent.mPrivateFlags |= DRAW_ANIMATION;
+                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
 
                 final int left = mLeft + (int) region.left;
                 final int top = mTop + (int) region.top;
@@ -12872,7 +12963,7 @@
                     mTransformationInfo.matrix3D = new Matrix();
                 }
                 displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == PIVOT_EXPLICITLY_SET) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
                     displayList.setPivotX(getPivotX());
                     displayList.setPivotY(getPivotY());
                 }
@@ -12920,15 +13011,15 @@
             more = drawAnimation(parent, drawingTime, a, scalingRequired);
             concatMatrix = a.willChangeTransformationMatrix();
             if (concatMatrix) {
-                mPrivateFlags3 |= VIEW_IS_ANIMATING_TRANSFORM;
+                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
             }
             transformToApply = parent.mChildTransformation;
         } else {
-            if ((mPrivateFlags3 & VIEW_IS_ANIMATING_TRANSFORM) == VIEW_IS_ANIMATING_TRANSFORM &&
+            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == PFLAG3_VIEW_IS_ANIMATING_TRANSFORM &&
                     mDisplayList != null) {
                 // No longer animating: clear out old animation matrix
                 mDisplayList.setAnimationMatrix(null);
-                mPrivateFlags3 &= ~VIEW_IS_ANIMATING_TRANSFORM;
+                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
             }
             if (!useDisplayListProperties &&
                     (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
@@ -12947,21 +13038,21 @@
 
         // Sets the flag as early as possible to allow draw() implementations
         // to call invalidate() successfully when doing animations
-        mPrivateFlags |= DRAWN;
+        mPrivateFlags |= PFLAG_DRAWN;
 
         if (!concatMatrix && (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) == 0 &&
                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
-                (mPrivateFlags & DRAW_ANIMATION) == 0) {
-            mPrivateFlags2 |= VIEW_QUICK_REJECTED;
+                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
+            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
             return more;
         }
-        mPrivateFlags2 &= ~VIEW_QUICK_REJECTED;
+        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
 
         if (hardwareAccelerated) {
             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
             // retain the flag's value temporarily in the mRecreateDisplayList flag
-            mRecreateDisplayList = (mPrivateFlags & INVALIDATED) == INVALIDATED;
-            mPrivateFlags &= ~INVALIDATED;
+            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
+            mPrivateFlags &= ~PFLAG_INVALIDATED;
         }
 
         DisplayList displayList = null;
@@ -13045,7 +13136,7 @@
 
         float alpha = useDisplayListProperties ? 1 : getAlpha();
         if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
-                (mPrivateFlags3 & VIEW_IS_ANIMATING_ALPHA) == VIEW_IS_ANIMATING_ALPHA) {
+                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
             if (transformToApply != null || !childHasIdentityMatrix) {
                 int transX = 0;
                 int transY = 0;
@@ -13085,11 +13176,11 @@
 
             // Deal with alpha if it is or used to be <1
             if (alpha < 1 ||
-                    (mPrivateFlags3 & VIEW_IS_ANIMATING_ALPHA) == VIEW_IS_ANIMATING_ALPHA) {
+                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
                 if (alpha < 1) {
-                    mPrivateFlags3 |= VIEW_IS_ANIMATING_ALPHA;
+                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
                 } else {
-                    mPrivateFlags3 &= ~VIEW_IS_ANIMATING_ALPHA;
+                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
                 }
                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
                 if (hasNoCache) {
@@ -13110,13 +13201,13 @@
                         }
                     } else {
                         // Alpha is handled by the child directly, clobber the layer's alpha
-                        mPrivateFlags |= ALPHA_SET;
+                        mPrivateFlags |= PFLAG_ALPHA_SET;
                     }
                 }
             }
-        } else if ((mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
+        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
             onSetAlpha(255);
-            mPrivateFlags &= ~ALPHA_SET;
+            mPrivateFlags &= ~PFLAG_ALPHA_SET;
         }
 
         if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
@@ -13163,19 +13254,19 @@
             if (!layerRendered) {
                 if (!hasDisplayList) {
                     // Fast path for layouts with no backgrounds
-                    if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                        mPrivateFlags &= ~DIRTY_MASK;
+                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
+                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                         dispatchDraw(canvas);
                     } else {
                         draw(canvas);
                     }
                 } else {
-                    mPrivateFlags &= ~DIRTY_MASK;
+                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                     ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
                 }
             }
         } else if (cache != null) {
-            mPrivateFlags &= ~DIRTY_MASK;
+            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
             Paint cachePaint;
 
             if (layerType == LAYER_TYPE_NONE) {
@@ -13215,7 +13306,7 @@
             // display lists to render, force an invalidate to allow the animation to
             // continue drawing another frame
             parent.invalidate(true);
-            if (a.hasAlpha() && (mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
+            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
                 // alpha animations should cause the child to recreate its display list
                 invalidate(true);
             }
@@ -13237,9 +13328,9 @@
      */
     public void draw(Canvas canvas) {
         final int privateFlags = mPrivateFlags;
-        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
+        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
-        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
+        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
 
         /*
          * Draw traversal performs several drawing steps which must be executed
@@ -13494,12 +13585,12 @@
         String output = "";
         int numFlags = 0;
 
-        if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
+        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
             output += "WANTS_FOCUS";
             numFlags++;
         }
 
-        if ((privateFlags & FOCUSED) == FOCUSED) {
+        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13507,7 +13598,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & SELECTED) == SELECTED) {
+        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13515,7 +13606,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
+        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13523,7 +13614,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13531,7 +13622,7 @@
             numFlags++;
         }
 
-        if ((privateFlags & DRAWN) == DRAWN) {
+        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
             if (numFlags > 0) {
                 output += " ";
             }
@@ -13548,7 +13639,7 @@
      * @return true if the layout will be forced during next layout pass
      */
     public boolean isLayoutRequested() {
-        return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
+        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
     }
 
     /**
@@ -13578,9 +13669,9 @@
         int oldB = mBottom;
         int oldR = mRight;
         boolean changed = setFrame(l, t, r, b);
-        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
+        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
             onLayout(changed, l, t, r, b);
-            mPrivateFlags &= ~LAYOUT_REQUIRED;
+            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
 
             ListenerInfo li = mListenerInfo;
             if (li != null && li.mOnLayoutChangeListeners != null) {
@@ -13592,7 +13683,7 @@
                 }
             }
         }
-        mPrivateFlags &= ~FORCE_LAYOUT;
+        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
     }
 
     /**
@@ -13636,7 +13727,7 @@
             changed = true;
 
             // Remember our drawn bit
-            int drawn = mPrivateFlags & DRAWN;
+            int drawn = mPrivateFlags & PFLAG_DRAWN;
 
             int oldWidth = mRight - mLeft;
             int oldHeight = mBottom - mTop;
@@ -13655,11 +13746,11 @@
                 mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
             }
 
-            mPrivateFlags |= HAS_BOUNDS;
+            mPrivateFlags |= PFLAG_HAS_BOUNDS;
 
 
             if (sizeChanged) {
-                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
                     // A change in dimension means an auto-centered pivot point changes, too
                     if (mTransformationInfo != null) {
                         mTransformationInfo.mMatrixDirty = true;
@@ -13674,7 +13765,7 @@
                 // This is because someone may have invalidated this view
                 // before this call to setFrame came in, thereby clearing
                 // the DRAWN bit.
-                mPrivateFlags |= DRAWN;
+                mPrivateFlags |= PFLAG_DRAWN;
                 invalidate(sizeChanged);
                 // parent display list may need to be recreated based on a change in the bounds
                 // of any child
@@ -13852,7 +13943,7 @@
      * @see #getDrawableState
      */
     public void refreshDrawableState() {
-        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
+        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
         drawableStateChanged();
 
         ViewParent parent = mParent;
@@ -13872,11 +13963,11 @@
      * @see #onCreateDrawableState(int)
      */
     public final int[] getDrawableState() {
-        if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
+        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
             return mDrawableState;
         } else {
             mDrawableState = onCreateDrawableState(0);
-            mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
+            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
             return mDrawableState;
         }
     }
@@ -13907,12 +13998,12 @@
         int privateFlags = mPrivateFlags;
 
         int viewStateIndex = 0;
-        if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
+        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
         if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
-        if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
+        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
         if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
-        if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
+        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
                 HardwareRenderer.isAvailable()) {
             // This is set if HW acceleration is requested, even if the current
@@ -13920,11 +14011,11 @@
             // windows to better match their app.
             viewStateIndex |= VIEW_STATE_ACCELERATED;
         }
-        if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
+        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
 
         final int privateFlags2 = mPrivateFlags2;
-        if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
-        if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
+        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
+        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
 
         drawableState = VIEW_STATE_SETS[viewStateIndex];
 
@@ -13932,10 +14023,10 @@
         if (false) {
             Log.i("View", "drawableStateIndex=" + viewStateIndex);
             Log.i("View", toString()
-                    + " pressed=" + ((privateFlags & PRESSED) != 0)
+                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
                     + " fo=" + hasFocus()
-                    + " sl=" + ((privateFlags & SELECTED) != 0)
+                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
                     + " wf=" + hasWindowFocus()
                     + ": " + Arrays.toString(drawableState));
         }
@@ -14076,7 +14167,7 @@
             background.setLayoutDirection(getResolvedLayoutDirection());
             if (background.getPadding(padding)) {
                 // Reset padding resolution
-                mPrivateFlags2 &= ~PADDING_RESOLVED;
+                mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
                 switch (background.getLayoutDirection()) {
                     case LAYOUT_DIRECTION_RTL:
                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
@@ -14101,23 +14192,23 @@
             background.setVisible(getVisibility() == VISIBLE, false);
             mBackground = background;
 
-            if ((mPrivateFlags & SKIP_DRAW) != 0) {
-                mPrivateFlags &= ~SKIP_DRAW;
-                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
+            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
+                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
+                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
                 requestLayout = true;
             }
         } else {
             /* Remove the background */
             mBackground = null;
 
-            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
+            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
                 /*
                  * This view ONLY drew the background before and we're removing
                  * the background, so now it won't draw anything
                  * (hence we SKIP_DRAW)
                  */
-                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
-                mPrivateFlags |= SKIP_DRAW;
+                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
+                mPrivateFlags |= PFLAG_SKIP_DRAW;
             }
 
             /*
@@ -14174,7 +14265,7 @@
      */
     public void setPadding(int left, int top, int right, int bottom) {
         // Reset padding resolution
-        mPrivateFlags2 &= ~PADDING_RESOLVED;
+        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
 
         mUserPaddingStart = UNDEFINED_PADDING;
         mUserPaddingEnd = UNDEFINED_PADDING;
@@ -14261,7 +14352,7 @@
      */
     public void setPaddingRelative(int start, int top, int end, int bottom) {
         // Reset padding resolution
-        mPrivateFlags2 &= ~PADDING_RESOLVED;
+        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
 
         mUserPaddingStart = start;
         mUserPaddingEnd = end;
@@ -14392,8 +14483,8 @@
      * @param selected true if the view must be selected, false otherwise
      */
     public void setSelected(boolean selected) {
-        if (((mPrivateFlags & SELECTED) != 0) != selected) {
-            mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
+        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
+            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
             if (!selected) resetPressedState();
             invalidate(true);
             refreshDrawableState();
@@ -14421,7 +14512,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isSelected() {
-        return (mPrivateFlags & SELECTED) != 0;
+        return (mPrivateFlags & PFLAG_SELECTED) != 0;
     }
 
     /**
@@ -14438,8 +14529,8 @@
      * @param activated true if the view must be activated, false otherwise
      */
     public void setActivated(boolean activated) {
-        if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
-            mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
+        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
+            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
             invalidate(true);
             refreshDrawableState();
             dispatchSetActivated(activated);
@@ -14463,7 +14554,7 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isActivated() {
-        return (mPrivateFlags & ACTIVATED) != 0;
+        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
     }
 
     /**
@@ -14751,9 +14842,9 @@
      */
     public void setIsRootNamespace(boolean isRoot) {
         if (isRoot) {
-            mPrivateFlags |= IS_ROOT_NAMESPACE;
+            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
         } else {
-            mPrivateFlags &= ~IS_ROOT_NAMESPACE;
+            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
         }
     }
 
@@ -14763,7 +14854,7 @@
      * @return true if the view belongs to the root namespace, false otherwise
      */
     public boolean isRootNamespace() {
-        return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
+        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
     }
 
     /**
@@ -14912,7 +15003,7 @@
         }
         Log.d(VIEW_LOG_TAG, output);
 
-        if ((mPrivateFlags & FOCUSED) != 0) {
+        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
             output = debugIndent(depth) + " FOCUSED";
             Log.d(VIEW_LOG_TAG, output);
         }
@@ -14992,8 +15083,8 @@
      * tree.
      */
     public void requestLayout() {
-        mPrivateFlags |= FORCE_LAYOUT;
-        mPrivateFlags |= INVALIDATED;
+        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
+        mPrivateFlags |= PFLAG_INVALIDATED;
 
         if (mParent != null && !mParent.isLayoutRequested()) {
             mParent.requestLayout();
@@ -15006,8 +15097,8 @@
      * on the parent.
      */
     public void forceLayout() {
-        mPrivateFlags |= FORCE_LAYOUT;
-        mPrivateFlags |= INVALIDATED;
+        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
+        mPrivateFlags |= PFLAG_INVALIDATED;
     }
 
     /**
@@ -15031,12 +15122,12 @@
      * @see #onMeasure(int, int)
      */
     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
-        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
+        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
                 widthMeasureSpec != mOldWidthMeasureSpec ||
                 heightMeasureSpec != mOldHeightMeasureSpec) {
 
             // first clears the measured dimension flag
-            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
+            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
 
             if (!isPaddingResolved()) {
                 resolvePadding();
@@ -15047,13 +15138,13 @@
 
             // flag not set, setMeasuredDimension() was not invoked, we raise
             // an exception to warn the developer
-            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
+            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
                 throw new IllegalStateException("onMeasure() did not set the"
                         + " measured dimension by calling"
                         + " setMeasuredDimension()");
             }
 
-            mPrivateFlags |= LAYOUT_REQUIRED;
+            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
         }
 
         mOldWidthMeasureSpec = widthMeasureSpec;
@@ -15127,7 +15218,7 @@
         mMeasuredWidth = measuredWidth;
         mMeasuredHeight = measuredHeight;
 
-        mPrivateFlags |= MEASURED_DIMENSION_SET;
+        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
     }
 
     /**
@@ -15371,7 +15462,7 @@
      * @see #getAnimation()
      */
     protected void onAnimationStart() {
-        mPrivateFlags |= ANIMATION_STARTED;
+        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
     }
 
     /**
@@ -15383,7 +15474,7 @@
      * @see #getAnimation()
      */
     protected void onAnimationEnd() {
-        mPrivateFlags &= ~ANIMATION_STARTED;
+        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
     }
 
     /**
@@ -15420,14 +15511,14 @@
         final AttachInfo attachInfo = mAttachInfo;
         if (region != null && attachInfo != null) {
             final int pflags = mPrivateFlags;
-            if ((pflags & SKIP_DRAW) == 0) {
+            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
                 // remove it from the transparent region.
                 final int[] location = attachInfo.mTransparentLocation;
                 getLocationInWindow(location);
                 region.op(location[0], location[1], location[0] + mRight - mLeft,
                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
-            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
+            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
                 // exists, so we remove the background drawable's non-transparent
                 // parts from this transparent region.
@@ -15904,7 +15995,7 @@
     }
 
     boolean canAcceptDrag() {
-        return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
+        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
     }
 
     /**
@@ -16169,7 +16260,7 @@
             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
     })
     public int getTextDirection() {
-        return (mPrivateFlags2 & TEXT_DIRECTION_MASK) >> TEXT_DIRECTION_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
     }
 
     /**
@@ -16187,10 +16278,10 @@
     public void setTextDirection(int textDirection) {
         if (getTextDirection() != textDirection) {
             // Reset the current text direction and the resolved one
-            mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
+            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
             resetResolvedTextDirection();
             // Set the new text direction
-            mPrivateFlags2 |= ((textDirection << TEXT_DIRECTION_MASK_SHIFT) & TEXT_DIRECTION_MASK);
+            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
             // Refresh
             requestLayout();
             invalidate(true);
@@ -16215,10 +16306,10 @@
      */
     public int getResolvedTextDirection() {
         // The text direction will be resolved only if needed
-        if ((mPrivateFlags2 & TEXT_DIRECTION_RESOLVED) != TEXT_DIRECTION_RESOLVED) {
+        if ((mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) != PFLAG2_TEXT_DIRECTION_RESOLVED) {
             resolveTextDirection();
         }
-        return (mPrivateFlags2 & TEXT_DIRECTION_RESOLVED_MASK) >> TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
     }
 
     /**
@@ -16227,7 +16318,7 @@
      */
     public void resolveTextDirection() {
         // Reset any previous text direction resolution
-        mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
 
         if (hasRtlSupport()) {
             // Set resolved text direction flag depending on text direction flag
@@ -16246,15 +16337,15 @@
                             case TEXT_DIRECTION_RTL:
                             case TEXT_DIRECTION_LOCALE:
                                 mPrivateFlags2 |=
-                                        (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                                        (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
                                 break;
                             default:
                                 // Default resolved direction is "first strong" heuristic
-                                mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                                mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                         }
                     } else {
                         // We cannot do the resolution if there is no parent, so use the default one
-                        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
                     }
                     break;
                 case TEXT_DIRECTION_FIRST_STRONG:
@@ -16263,19 +16354,19 @@
                 case TEXT_DIRECTION_RTL:
                 case TEXT_DIRECTION_LOCALE:
                     // Resolved direction is the same as text direction
-                    mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
                     break;
                 default:
                     // Default resolved direction is "first strong" heuristic
-                    mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
             }
         } else {
             // Default resolved direction is "first strong" heuristic
-            mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
         }
 
         // Set to resolved
-        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED;
+        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
         onResolvedTextDirectionChanged();
     }
 
@@ -16308,7 +16399,7 @@
      * reset is done.
      */
     public void resetResolvedTextDirection() {
-        mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
         onResolvedTextDirectionReset();
     }
 
@@ -16344,7 +16435,7 @@
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
     })
     public int getTextAlignment() {
-        return (mPrivateFlags2 & TEXT_ALIGNMENT_MASK) >> TEXT_ALIGNMENT_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
     }
 
     /**
@@ -16365,10 +16456,10 @@
     public void setTextAlignment(int textAlignment) {
         if (textAlignment != getTextAlignment()) {
             // Reset the current and resolved text alignment
-            mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
             resetResolvedTextAlignment();
             // Set the new text alignment
-            mPrivateFlags2 |= ((textAlignment << TEXT_ALIGNMENT_MASK_SHIFT) & TEXT_ALIGNMENT_MASK);
+            mPrivateFlags2 |= ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
             // Refresh
             requestLayout();
             invalidate(true);
@@ -16402,10 +16493,10 @@
     })
     public int getResolvedTextAlignment() {
         // If text alignment is not resolved, then resolve it
-        if ((mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED) != TEXT_ALIGNMENT_RESOLVED) {
+        if ((mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) != PFLAG2_TEXT_ALIGNMENT_RESOLVED) {
             resolveTextAlignment();
         }
-        return (mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED_MASK) >> TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
     }
 
     /**
@@ -16414,7 +16505,7 @@
      */
     public void resolveTextAlignment() {
         // Reset any previous text alignment resolution
-        mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
 
         if (hasRtlSupport()) {
             // Set resolved text alignment flag depending on text alignment flag
@@ -16436,16 +16527,16 @@
                                 // Resolved text alignment is the same as the parent resolved
                                 // text alignment
                                 mPrivateFlags2 |=
-                                        (parentResolvedTextAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+                                        (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
                                 break;
                             default:
                                 // Use default resolved text alignment
-                                mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                                mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                         }
                     }
                     else {
                         // We cannot do the resolution if there is no parent so use the default
-                        mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
                     }
                     break;
                 case TEXT_ALIGNMENT_GRAVITY:
@@ -16455,19 +16546,19 @@
                 case TEXT_ALIGNMENT_VIEW_START:
                 case TEXT_ALIGNMENT_VIEW_END:
                     // Resolved text alignment is the same as text alignment
-                    mPrivateFlags2 |= (textAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
                     break;
                 default:
                     // Use default resolved text alignment
-                    mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
             }
         } else {
             // Use default resolved text alignment
-            mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
         }
 
         // Set the resolved
-        mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED;
+        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
         onResolvedTextAlignmentChanged();
     }
 
@@ -16501,7 +16592,7 @@
      */
     public void resetResolvedTextAlignment() {
         // Reset any previous text alignment resolution
-        mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
+        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
         onResolvedTextAlignmentReset();
     }
 
@@ -16831,7 +16922,7 @@
 
     private final class CheckForTap implements Runnable {
         public void run() {
-            mPrivateFlags &= ~PREPRESSED;
+            mPrivateFlags &= ~PFLAG_PREPRESSED;
             setPressed(true);
             checkForLongClick(ViewConfiguration.getTapTimeout());
         }
@@ -17179,6 +17270,8 @@
 
         final IBinder mWindowToken;
 
+        final Display mDisplay;
+
         final Callbacks mRootCallbacks;
 
         HardwareCanvas mHardwareCanvas;
@@ -17438,11 +17531,12 @@
          *
          * @param handler the events handler the view must use
          */
-        AttachInfo(IWindowSession session, IWindow window,
+        AttachInfo(IWindowSession session, IWindow window, Display display,
                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
             mSession = session;
             mWindow = window;
             mWindowToken = window.asBinder();
+            mDisplay = display;
             mViewRootImpl = viewRootImpl;
             mHandler = handler;
             mRootCallbacks = effectPlayer;
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 3082976..499075e 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -279,7 +279,8 @@
         mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
 
         // Size of the screen in bytes, in ARGB_8888 format
-        final Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
+        final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        final Display display = win.getDefaultDisplay();
         final Point size = new Point();
         display.getRealSize(size);
         mMaximumDrawingCacheSize = 4 * size.x * size.y;
@@ -288,7 +289,7 @@
         mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
 
         if (!sHasPermanentMenuKeySet) {
-            IWindowManager wm = WindowManagerImpl.getWindowManagerService();
+            IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
             try {
                 sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar();
                 sHasPermanentMenuKeySet = true;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index dae9265..1286eb9 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -497,8 +497,8 @@
             throws IOException {
 
         long durationMeasure =
-                (root || (view.mPrivateFlags & View.MEASURED_DIMENSION_SET) != 0) ? profileViewOperation(
-                        view, new ViewOperation<Void>() {
+                (root || (view.mPrivateFlags & View.PFLAG_MEASURED_DIMENSION_SET) != 0)
+                ? profileViewOperation(view, new ViewOperation<Void>() {
                             public Void[] pre() {
                                 forceLayout(view);
                                 return null;
@@ -524,8 +524,8 @@
                         })
                         : 0;
         long durationLayout =
-                (root || (view.mPrivateFlags & View.LAYOUT_REQUIRED) != 0) ? profileViewOperation(
-                        view, new ViewOperation<Void>() {
+                (root || (view.mPrivateFlags & View.PFLAG_LAYOUT_REQUIRED) != 0)
+                ? profileViewOperation(view, new ViewOperation<Void>() {
                             public Void[] pre() {
                                 return null;
                             }
@@ -538,9 +538,8 @@
                             }
                         }) : 0;
         long durationDraw =
-                (root || !view.willNotDraw() || (view.mPrivateFlags & View.DRAWN) != 0) ? profileViewOperation(
-                        view,
-                        new ViewOperation<Object>() {
+                (root || !view.willNotDraw() || (view.mPrivateFlags & View.PFLAG_DRAWN) != 0)
+                ? profileViewOperation(view, new ViewOperation<Object>() {
                             public Object[] pre() {
                                 final DisplayMetrics metrics =
                                         (view != null && view.getResources() != null) ?
@@ -651,7 +650,7 @@
 
         final boolean localVisible = view.getVisibility() == View.VISIBLE && visible;
 
-        if ((view.mPrivateFlags & View.SKIP_DRAW) != View.SKIP_DRAW) {
+        if ((view.mPrivateFlags & View.PFLAG_SKIP_DRAW) != View.PFLAG_SKIP_DRAW) {
             final int id = view.getId();
             String name = view.getClass().getSimpleName();
             if (id != View.NO_ID) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index bfe0ca5..3ab0e94 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -804,7 +804,7 @@
      */
     @Override
     public boolean hasFocus() {
-        return (mPrivateFlags & FOCUSED) != 0 || mFocused != null;
+        return (mPrivateFlags & PFLAG_FOCUSED) != 0 || mFocused != null;
     }
 
     /*
@@ -898,7 +898,7 @@
         for (int i = 0; i < childrenCount; i++) {
             View child = children[i];
             if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
-                    && (child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+                    && (child.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
                 child.findViewsWithText(outViews, text, flags);
             }
         }
@@ -1177,7 +1177,7 @@
                     final View view = mCurrentDragView;
                     event.mAction = DragEvent.ACTION_DRAG_EXITED;
                     view.dispatchDragEvent(event);
-                    view.mPrivateFlags2 &= ~View.DRAG_HOVERED;
+                    view.mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
                     view.refreshDrawableState();
                 }
                 mCurrentDragView = target;
@@ -1186,7 +1186,7 @@
                 if (target != null) {
                     event.mAction = DragEvent.ACTION_DRAG_ENTERED;
                     target.dispatchDragEvent(event);
-                    target.mPrivateFlags2 |= View.DRAG_HOVERED;
+                    target.mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
                     target.refreshDrawableState();
                 }
                 event.mAction = action;  // restore the event's original state
@@ -1220,7 +1220,7 @@
             if (mCurrentDragView != null) {
                 final View view = mCurrentDragView;
                 view.dispatchDragEvent(event);
-                view.mPrivateFlags2 &= ~View.DRAG_HOVERED;
+                view.mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
                 view.refreshDrawableState();
 
                 mCurrentDragView = null;
@@ -1281,7 +1281,7 @@
             mDragNotifiedChildren.add(child);
             canAccept = child.dispatchDragEvent(mCurrentDrag);
             if (canAccept && !child.canAcceptDrag()) {
-                child.mPrivateFlags2 |= View.DRAG_CAN_ACCEPT;
+                child.mPrivateFlags2 |= View.PFLAG2_DRAG_CAN_ACCEPT;
                 child.refreshDrawableState();
             }
         }
@@ -1330,9 +1330,11 @@
      */
     @Override
     public boolean dispatchKeyEventPreIme(KeyEvent event) {
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             return super.dispatchKeyEventPreIme(event);
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             return mFocused.dispatchKeyEventPreIme(event);
         }
         return false;
@@ -1347,11 +1349,13 @@
             mInputEventConsistencyVerifier.onKeyEvent(event, 1);
         }
 
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             if (super.dispatchKeyEvent(event)) {
                 return true;
             }
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             if (mFocused.dispatchKeyEvent(event)) {
                 return true;
             }
@@ -1368,9 +1372,11 @@
      */
     @Override
     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             return super.dispatchKeyShortcutEvent(event);
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             return mFocused.dispatchKeyShortcutEvent(event);
         }
         return false;
@@ -1385,11 +1391,13 @@
             mInputEventConsistencyVerifier.onTrackballEvent(event, 1);
         }
 
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             if (super.dispatchTrackballEvent(event)) {
                 return true;
             }
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             if (mFocused.dispatchTrackballEvent(event)) {
                 return true;
             }
@@ -1715,8 +1723,10 @@
             final float x = event.getX();
             final float y = event.getY();
 
+            final boolean customOrder = isChildrenDrawingOrderEnabled();
             for (int i = childrenCount - 1; i >= 0; i--) {
-                final View child = children[i];
+                final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
+                final View child = children[childIndex];
                 if (!canViewReceivePointerEvents(child)
                         || !isTransformedTouchPointInView(x, y, child, null)) {
                     continue;
@@ -1738,9 +1748,11 @@
     @Override
     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
         // Send the event to the focused child or to this view group if it has focus.
-        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
             return super.dispatchGenericFocusedEvent(event);
-        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
             return mFocused.dispatchGenericMotionEvent(event);
         }
         return false;
@@ -1841,8 +1853,11 @@
                         final float x = ev.getX(actionIndex);
                         final float y = ev.getY(actionIndex);
 
+                        final boolean customOrder = isChildrenDrawingOrderEnabled();
                         for (int i = childrenCount - 1; i >= 0; i--) {
-                            final View child = children[i];
+                            final int childIndex = customOrder ?
+                                    getChildDrawingOrder(childrenCount, i) : i;
+                            final View child = children[childIndex];
                             if (!canViewReceivePointerEvents(child)
                                     || !isTransformedTouchPointInView(x, y, child, null)) {
                                 continue;
@@ -1860,7 +1875,7 @@
                             if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                                 // Child wants to receive touch within its bounds.
                                 mLastTouchDownTime = ev.getDownTime();
-                                mLastTouchDownIndex = i;
+                                mLastTouchDownIndex = childIndex;
                                 mLastTouchDownX = ev.getX();
                                 mLastTouchDownY = ev.getY();
                                 newTouchTarget = addTouchTarget(child, idBitsToAssign);
@@ -1951,8 +1966,8 @@
      * Returns true if the flag was previously set.
      */
     private static boolean resetCancelNextUpFlag(View view) {
-        if ((view.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
-            view.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+        if ((view.mPrivateFlags & PFLAG_CANCEL_NEXT_UP_EVENT) != 0) {
+            view.mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
             return true;
         }
         return false;
@@ -2769,7 +2784,7 @@
         }
 
         // We will draw our child's animation, let's reset the flag
-        mPrivateFlags &= ~DRAW_ANIMATION;
+        mPrivateFlags &= ~PFLAG_DRAW_ANIMATION;
         mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED;
 
         boolean more = false;
@@ -2889,8 +2904,9 @@
             final View child = children[i];
             if (((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) &&
                     child.hasStaticLayer()) {
-                child.mRecreateDisplayList = (child.mPrivateFlags & INVALIDATED) == INVALIDATED;
-                child.mPrivateFlags &= ~INVALIDATED;
+                child.mRecreateDisplayList = (child.mPrivateFlags & PFLAG_INVALIDATED)
+                        == PFLAG_INVALIDATED;
+                child.mPrivateFlags &= ~PFLAG_INVALIDATED;
                 child.getDisplayList();
                 child.mRecreateDisplayList = false;
             }
@@ -3033,7 +3049,7 @@
         for (int i = 0; i < len; i++) {
             View v = where[i];
 
-            if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+            if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
                 v = v.findViewById(id);
 
                 if (v != null) {
@@ -3060,7 +3076,7 @@
         for (int i = 0; i < len; i++) {
             View v = where[i];
 
-            if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+            if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
                 v = v.findViewWithTag(tag);
 
                 if (v != null) {
@@ -3087,7 +3103,7 @@
         for (int i = 0; i < len; i++) {
             View v = where[i];
 
-            if (v != childToSkip && (v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+            if (v != childToSkip && (v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
                 v = v.findViewByPredicate(predicate);
 
                 if (v != null) {
@@ -3297,7 +3313,7 @@
             boolean preventRequestLayout) {
         child.mParent = null;
         addViewInner(child, index, params, preventRequestLayout);
-        child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN;
+        child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
         return true;
     }
 
@@ -3307,7 +3323,7 @@
      * @param child the child on which to perform the cleanup
      */
     protected void cleanupLayoutState(View child) {
-        child.mPrivateFlags &= ~View.FORCE_LAYOUT;
+        child.mPrivateFlags &= ~View.PFLAG_FORCE_LAYOUT;
     }
 
     private void addViewInner(View child, int index, LayoutParams params,
@@ -3854,9 +3870,10 @@
         addInArray(child, index);
 
         child.mParent = this;
-        child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK & ~DRAWING_CACHE_VALID) |
-                DRAWN | INVALIDATED;
-        this.mPrivateFlags |= INVALIDATED;
+        child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK
+                        & ~PFLAG_DRAWING_CACHE_VALID)
+                | PFLAG_DRAWN | PFLAG_INVALIDATED;
+        this.mPrivateFlags |= PFLAG_INVALIDATED;
 
         if (child.hasFocus()) {
             requestChildFocus(child, child.findFocus());
@@ -3957,7 +3974,8 @@
             // If the child is drawing an animation, we want to copy this flag onto
             // ourselves and the parent to make sure the invalidate request goes
             // through
-            final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;
+            final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION)
+                    == PFLAG_DRAW_ANIMATION;
 
             // Check whether the child that requests the invalidate is fully opaque
             // Views being animated or transformed are not considered opaque because we may
@@ -3967,11 +3985,11 @@
                     child.getAnimation() == null && childMatrix.isIdentity();
             // Mark the child as dirty, using the appropriate flag
             // Make sure we do not set both flags at the same time
-            int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
+            int opaqueFlag = isOpaque ? PFLAG_DIRTY_OPAQUE : PFLAG_DIRTY;
 
             if (child.mLayerType != LAYER_TYPE_NONE) {
-                mPrivateFlags |= INVALIDATED;
-                mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                mPrivateFlags |= PFLAG_INVALIDATED;
+                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
                 child.mLocalDirtyRect.union(dirty);
             }
 
@@ -4013,7 +4031,7 @@
 
                 if (drawAnimation) {
                     if (view != null) {
-                        view.mPrivateFlags |= DRAW_ANIMATION;
+                        view.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
                     } else if (parent instanceof ViewRootImpl) {
                         ((ViewRootImpl) parent).mIsAnimating = true;
                     }
@@ -4024,10 +4042,10 @@
                 if (view != null) {
                     if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&
                             view.getSolidColor() == 0) {
-                        opaqueFlag = DIRTY;
+                        opaqueFlag = PFLAG_DIRTY;
                     }
-                    if ((view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
-                        view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
+                    if ((view.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) {
+                        view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | opaqueFlag;
                     }
                 }
 
@@ -4058,8 +4076,8 @@
      * does not intersect with this ViewGroup's bounds.
      */
     public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
-        if ((mPrivateFlags & DRAWN) == DRAWN ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
             if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=
                         FLAG_OPTIMIZE_INVALIDATE) {
                 dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,
@@ -4073,20 +4091,20 @@
                         dirty.setEmpty();
                     }
                 }
-                mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
 
                 location[CHILD_LEFT_INDEX] = left;
                 location[CHILD_TOP_INDEX] = top;
 
                 if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= INVALIDATED;
+                    mPrivateFlags |= PFLAG_INVALIDATED;
                     mLocalDirtyRect.union(dirty);
                 }
 
                 return mParent;
 
             } else {
-                mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~PFLAG_DRAWN & ~PFLAG_DRAWING_CACHE_VALID;
 
                 location[CHILD_LEFT_INDEX] = mLeft;
                 location[CHILD_TOP_INDEX] = mTop;
@@ -4098,7 +4116,7 @@
                 }
 
                 if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= INVALIDATED;
+                    mPrivateFlags |= PFLAG_INVALIDATED;
                     mLocalDirtyRect.union(dirty);
                 }
 
@@ -4160,8 +4178,8 @@
      * coordinate system, pruning the invalidation if the parent has already been invalidated.
      */
     private ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) {
-        if ((mPrivateFlags & DRAWN) == DRAWN ||
-                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
+                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
             dirty.offset(left - mScrollX, top - mScrollY);
 
             if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0 ||
@@ -4924,11 +4942,11 @@
             view.clearAnimation();
         }
 
-        if ((view.mPrivateFlags & ANIMATION_STARTED) == ANIMATION_STARTED) {
+        if ((view.mPrivateFlags & PFLAG_ANIMATION_STARTED) == PFLAG_ANIMATION_STARTED) {
             view.onAnimationEnd();
             // Should be performed by onAnimationEnd() but this avoid an infinite loop,
             // so we'd rather be safe than sorry
-            view.mPrivateFlags &= ~ANIMATION_STARTED;
+            view.mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
             // Draw one more frame after the animation is done
             mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
         }
@@ -5027,7 +5045,7 @@
     @Override
     public boolean gatherTransparentRegion(Region region) {
         // If no transparent regions requested, we are always opaque.
-        final boolean meOpaque = (mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) == 0;
+        final boolean meOpaque = (mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0;
         if (meOpaque && region == null) {
             // The caller doesn't care about the region, so stop now.
             return true;
@@ -5052,7 +5070,7 @@
      */
     public void requestTransparentRegion(View child) {
         if (child != null) {
-            child.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
+            child.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
             if (mParent != null) {
                 mParent.requestTransparentRegion(this);
             }
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index ce6f4c5..d8db14c 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -1036,7 +1036,7 @@
             if ((propertyMask & TRANSFORM_MASK) != 0) {
                 mView.mTransformationInfo.mMatrixDirty = true;
                 if (!useDisplayListProperties) {
-                    mView.mPrivateFlags |= View.DRAWN; // force another invalidation
+                    mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
                 }
             }
             // invalidate(false) in all cases except if alphaHandled gets set to true
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index afcbaaf..725d9b5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -18,7 +18,6 @@
 
 import android.Manifest;
 import android.animation.LayoutTransition;
-import android.animation.ValueAnimator;
 import android.app.ActivityManagerNative;
 import android.content.ClipDescription;
 import android.content.ComponentCallbacks;
@@ -88,7 +87,7 @@
 /**
  * The top of a view hierarchy, implementing the needed protocol between View
  * and the WindowManager.  This is for the most part an internal implementation
- * detail of {@link WindowManagerImpl}.
+ * detail of {@link WindowManagerGlobal}.
  *
  * {@hide}
  */
@@ -126,11 +125,6 @@
      */
     static final int MAX_TRACKBALL_DELAY = 250;
 
-    static IWindowSession sWindowSession;
-
-    static final Object mStaticInit = new Object();
-    static boolean mInitialized = false;
-
     static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();
 
     static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<Runnable>();
@@ -143,6 +137,9 @@
     private static boolean sRenderThreadQueried = false;
     private static final Object[] sRenderThreadQueryLock = new Object[0];
 
+    final IWindowSession mWindowSession;
+    final Display mDisplay;
+
     long mLastTrackballTime = 0;
     final TrackballAxis mTrackballAxisX = new TrackballAxis();
     final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -250,7 +247,7 @@
     boolean mAdded;
     boolean mAddedTouchMode;
 
-    CompatibilityInfoHolder mCompatibilityInfo;
+    final CompatibilityInfoHolder mCompatibilityInfo;
 
     // These are accessed by multiple threads.
     final Rect mWinFrame; // frame given by window manager.
@@ -322,24 +319,6 @@
             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                     new InputEventConsistencyVerifier(this, 0) : null;
 
-    public static IWindowSession getWindowSession(Looper mainLooper) {
-        synchronized (mStaticInit) {
-            if (!mInitialized) {
-                try {
-                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
-                    IWindowManager windowManager = WindowManagerImpl.getWindowManagerService();
-                    sWindowSession = windowManager.openSession(
-                            imm.getClient(), imm.getInputContext());
-                    float animatorScale = windowManager.getAnimationScale(2);
-                    ValueAnimator.setDurationScale(animatorScale);
-                    mInitialized = true;
-                } catch (RemoteException e) {
-                }
-            }
-            return sWindowSession;
-        }
-    }
-
     static final class SystemUiVisibilityInfo {
         int seq;
         int globalVisibility;
@@ -347,7 +326,7 @@
         int localChanges;
     }
     
-    public ViewRootImpl(Context context) {
+    public ViewRootImpl(Context context, Display display) {
         super();
 
         if (MEASURE_LATENCY) {
@@ -359,7 +338,11 @@
         // Initialize the statics when this class is first instantiated. This is
         // done here instead of in the static block because Zygote does not
         // allow the spawning of threads.
-        getWindowSession(context.getMainLooper());
+        mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
+        mDisplay = display;
+
+        CompatibilityInfoHolder cih = display.getCompatibilityInfo();
+        mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();
 
         mThread = Thread.currentThread();
         mLocation = new WindowLeaked(null);
@@ -383,7 +366,7 @@
             new AccessibilityInteractionConnectionManager();
         mAccessibilityManager.addAccessibilityStateChangeListener(
                 mAccessibilityInteractionConnectionManager);
-        mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, mHandler, this);
+        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
         mViewConfiguration = ViewConfiguration.get(context);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
         mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
@@ -460,9 +443,10 @@
      * @hide
      */
     static boolean isInTouchMode() {
-        if (mInitialized) {
+        IWindowSession windowSession = WindowManagerGlobal.peekWindowSession();
+        if (windowSession != null) {
             try {
-                return sWindowSession.getInTouchMode();
+                return windowSession.getInTouchMode();
             } catch (RemoteException e) {
             }
         }
@@ -541,8 +525,8 @@
                     mOrigWindowType = mWindowAttributes.type;
                     mAttachInfo.mRecomputeGlobalAttributes = true;
                     collectViewAttributes();
-                    res = sWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
-                            getHostVisibility(), Display.DEFAULT_DISPLAY,
+                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
+                            getHostVisibility(), mDisplay.getDisplayId(),
                             mAttachInfo.mContentInsets, mInputChannel);
                 } catch (RemoteException e) {
                     mAdded = false;
@@ -565,7 +549,7 @@
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
                 if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
-                if (res < WindowManagerImpl.ADD_OKAY) {
+                if (res < WindowManagerGlobal.ADD_OKAY) {
                     mView = null;
                     mAttachInfo.mRootView = null;
                     mAdded = false;
@@ -573,33 +557,33 @@
                     unscheduleTraversals();
                     setAccessibilityFocus(null, null);
                     switch (res) {
-                        case WindowManagerImpl.ADD_BAD_APP_TOKEN:
-                        case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
+                        case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- token " + attrs.token
                                 + " is not valid; is your activity running?");
-                        case WindowManagerImpl.ADD_NOT_APP_TOKEN:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- token " + attrs.token
                                 + " is not for an application");
-                        case WindowManagerImpl.ADD_APP_EXITING:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_APP_EXITING:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- app for token " + attrs.token
                                 + " is exiting");
-                        case WindowManagerImpl.ADD_DUPLICATE_ADD:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_DUPLICATE_ADD:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window -- window " + mWindow
                                 + " has already been added");
-                        case WindowManagerImpl.ADD_STARTING_NOT_NEEDED:
+                        case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
                             // Silently ignore -- we would have just removed it
                             // right away, anyway.
                             return;
-                        case WindowManagerImpl.ADD_MULTIPLE_SINGLETON:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window " + mWindow +
                                 " -- another window of this type already exists");
-                        case WindowManagerImpl.ADD_PERMISSION_DENIED:
-                            throw new WindowManagerImpl.BadTokenException(
+                        case WindowManagerGlobal.ADD_PERMISSION_DENIED:
+                            throw new WindowManager.BadTokenException(
                                 "Unable to add window " + mWindow +
                                 " -- permission denied for this window type");
                     }
@@ -622,8 +606,8 @@
                 }
 
                 view.assignParent(this);
-                mAddedTouchMode = (res&WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE) != 0;
-                mAppVisible = (res&WindowManagerImpl.ADD_FLAG_APP_VISIBLE) != 0;
+                mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
+                mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
 
                 if (mAccessibilityManager.isEnabled()) {
                     mAccessibilityInteractionConnectionManager.ensureConnection();
@@ -1164,9 +1148,8 @@
 
             if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
                 // NOTE -- system code, won't try to do compat mode.
-                Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
                 Point size = new Point();
-                disp.getRealSize(size);
+                mDisplay.getRealSize(size);
                 desiredWindowWidth = size.x;
                 desiredWindowHeight = size.y;
             } else {
@@ -1251,9 +1234,8 @@
 
                     if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
                         // NOTE -- system code, won't try to do compat mode.
-                        Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
                         Point size = new Point();
-                        disp.getRealSize(size);
+                        mDisplay.getRealSize(size);
                         desiredWindowWidth = size.x;
                         desiredWindowHeight = size.y;
                     } else {
@@ -1303,7 +1285,7 @@
             }
         }
 
-        if (params != null && (host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
+        if (params != null && (host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
             if (!PixelFormat.formatHasAlpha(params.format)) {
                 params.format = PixelFormat.TRANSLUCENT;
             }
@@ -1502,7 +1484,7 @@
                             } catch (Surface.OutOfResourcesException e) {
                                 Log.e(TAG, "OutOfResourcesException initializing HW surface", e);
                                 try {
-                                    if (!sWindowSession.outOfMemory(mWindow)) {
+                                    if (!mWindowSession.outOfMemory(mWindow)) {
                                         Slog.w(TAG, "No processes killed for memory; killing self");
                                         Process.killProcess(Process.myPid());
                                     }
@@ -1535,7 +1517,7 @@
                     } catch (Surface.OutOfResourcesException e) {
                         Log.e(TAG, "OutOfResourcesException updating HW surface", e);
                         try {
-                            if (!sWindowSession.outOfMemory(mWindow)) {
+                            if (!mWindowSession.outOfMemory(mWindow)) {
                                 Slog.w(TAG, "No processes killed for memory; killing self");
                                 Process.killProcess(Process.myPid());
                             }
@@ -1629,7 +1611,7 @@
 
             if (!mStopped) {
                 boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
-                        (relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
+                        (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
                 if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
                         || mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
                     int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
@@ -1709,7 +1691,7 @@
             // By this point all views have been sized and positionned
             // We can compute the transparent area
 
-            if ((host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
+            if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
                 // start out transparent
                 // TODO: AVOID THAT CALL BY CACHING THE RESULT?
                 host.getLocationInWindow(mTmpLocation);
@@ -1726,7 +1708,7 @@
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
                     try {
-                        sWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
+                        mWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
                     } catch (RemoteException e) {
                     }
                 }
@@ -1775,7 +1757,7 @@
                 }
 
                 try {
-                    sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
+                    mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
                             contentInsets, visibleInsets, touchableRegion);
                 } catch (RemoteException e) {
                 }
@@ -1800,7 +1782,7 @@
                             + mRealFocusedView);
                 }
             }
-            if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_ANIMATING) != 0) {
+            if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_ANIMATING) != 0) {
                 // The first time we relayout the window, if the system is
                 // doing window animations, we want to hold of on any future
                 // draws until the animation is done.
@@ -1831,7 +1813,7 @@
         }
 
         // Remember if we must report the next draw.
-        if ((relayoutResult & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
+        if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
             mReportNextDraw = true;
         }
 
@@ -1893,7 +1875,7 @@
         // the test below should not fail unless someone is messing with us
         checkThread();
         if (mView == child) {
-            mView.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
+            mView.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS;
             // Need to make sure we re-evaluate the window attributes next
             // time around, to ensure the window has the correct format.
             mWindowAttributesChanged = true;
@@ -2061,7 +2043,7 @@
                 }
             }
             try {
-                sWindowSession.finishDrawing(mWindow);
+                mWindowSession.finishDrawing(mWindow);
             } catch (RemoteException e) {
             }
         }
@@ -2217,7 +2199,7 @@
         } catch (Surface.OutOfResourcesException e) {
             Log.e(TAG, "OutOfResourcesException locking surface", e);
             try {
-                if (!sWindowSession.outOfMemory(mWindow)) {
+                if (!mWindowSession.outOfMemory(mWindow)) {
                     Slog.w(TAG, "No processes killed for memory; killing self");
                     Process.killProcess(Process.myPid());
                 }
@@ -2256,7 +2238,7 @@
             dirty.setEmpty();
             mIsAnimating = false;
             attachInfo.mDrawingTime = SystemClock.uptimeMillis();
-            mView.mPrivateFlags |= View.DRAWN;
+            mView.mPrivateFlags |= View.PFLAG_DRAWN;
 
             if (DEBUG_DRAW) {
                 Context cxt = mView.getContext();
@@ -2646,7 +2628,7 @@
             mInputEventReceiver = null;
         }
         try {
-            sWindowSession.remove(mWindow);
+            mWindowSession.remove(mWindow);
         } catch (RemoteException e) {
         }
         
@@ -2891,7 +2873,7 @@
                             } catch (Surface.OutOfResourcesException e) {
                                 Log.e(TAG, "OutOfResourcesException locking surface", e);
                                 try {
-                                    if (!sWindowSession.outOfMemory(mWindow)) {
+                                    if (!mWindowSession.outOfMemory(mWindow)) {
                                         Slog.w(TAG, "No processes killed for memory; killing self");
                                         Process.killProcess(Process.myPid());
                                     }
@@ -3036,7 +3018,7 @@
 
         // tell the window manager
         try {
-            sWindowSession.setInTouchMode(inTouchMode);
+            mWindowSession.setInTouchMode(inTouchMode);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
@@ -3750,10 +3732,10 @@
                 if (prevDragView != mCurrentDragView) {
                     try {
                         if (prevDragView != null) {
-                            sWindowSession.dragRecipientExited(mWindow);
+                            mWindowSession.dragRecipientExited(mWindow);
                         }
                         if (mCurrentDragView != null) {
-                            sWindowSession.dragRecipientEntered(mWindow);
+                            mWindowSession.dragRecipientEntered(mWindow);
                         }
                     } catch (RemoteException e) {
                         Slog.e(TAG, "Unable to note drag target change");
@@ -3765,7 +3747,7 @@
                     mDragDescription = null;
                     try {
                         Log.i(TAG, "Reporting drop result: " + result);
-                        sWindowSession.reportDropResult(mWindow, result);
+                        mWindowSession.reportDropResult(mWindow, result);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Unable to report drop result");
                     }
@@ -3867,11 +3849,11 @@
                 params.type = mOrigWindowType;
             }
         }
-        int relayoutResult = sWindowSession.relayout(
+        int relayoutResult = mWindowSession.relayout(
                 mWindow, mSeq, params,
                 (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                 (int) (mView.getMeasuredHeight() * appScale + 0.5f),
-                viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING : 0,
+                viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                 mWinFrame, mPendingContentInsets, mPendingVisibleInsets,
                 mPendingConfiguration, mSurface);
         //Log.d(TAG, "<<<<<< BACK FROM relayout");
@@ -3928,7 +3910,7 @@
      */
     public boolean performHapticFeedback(int effectId, boolean always) {
         try {
-            return sWindowSession.performHapticFeedback(mWindow, effectId, always);
+            return mWindowSession.performHapticFeedback(mWindow, effectId, always);
         } catch (RemoteException e) {
             return false;
         }
@@ -4007,8 +3989,8 @@
                         // animation info.
                         try {
                             if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
-                                    & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
-                                sWindowSession.finishDrawing(mWindow);
+                                    & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
+                                mWindowSession.finishDrawing(mWindow);
                             }
                         } catch (RemoteException e) {
                         }
@@ -4726,9 +4708,11 @@
 
     static class W extends IWindow.Stub {
         private final WeakReference<ViewRootImpl> mViewAncestor;
+        private final IWindowSession mWindowSession;
 
         W(ViewRootImpl viewAncestor) {
             mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
+            mWindowSession = viewAncestor.mWindowSession;
         }
 
         public void resized(Rect frame, Rect contentInsets,
@@ -4827,7 +4811,7 @@
                 boolean sync) {
             if (sync) {
                 try {
-                    sWindowSession.wallpaperOffsetsComplete(asBinder());
+                    mWindowSession.wallpaperOffsetsComplete(asBinder());
                 } catch (RemoteException e) {
                 }
             }
@@ -4837,7 +4821,7 @@
                 int z, Bundle extras, boolean sync) {
             if (sync) {
                 try {
-                    sWindowSession.wallpaperCommandComplete(asBinder(), null);
+                    mWindowSession.wallpaperCommandComplete(asBinder(), null);
                 } catch (RemoteException e) {
                 }
             }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index f57f056..a242895 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -16,7 +16,6 @@
 
 package android.view;
 
-import android.app.Application;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -455,7 +454,7 @@
      * display panels.  This is <em>not</em> used for displaying the
      * Window itself -- that must be done by the client.
      *
-     * @param wm The ViewManager for adding new windows.
+     * @param wm The window manager for adding new windows.
      */
     public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
         setWindowManager(wm, appToken, appName, false);
@@ -466,7 +465,7 @@
      * display panels.  This is <em>not</em> used for displaying the
      * Window itself -- that must be done by the client.
      *
-     * @param wm The ViewManager for adding new windows.
+     * @param wm The window manager for adding new windows.
      */
     public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
             boolean hardwareAccelerated) {
@@ -475,14 +474,9 @@
         mHardwareAccelerated = hardwareAccelerated
                 || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
         if (wm == null) {
-            wm = WindowManagerImpl.getDefault();
+            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
         }
-        mWindowManager = ((WindowManagerImpl)wm).makeLocal(this);
-    }
-
-    CompatibilityInfoHolder getCompatibilityInfo() {
-        Application app = (Application)mContext.getApplicationContext();
-        return app != null ? app.mLoadedApk.mCompatibilityInfo : null;
+        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
     }
 
     void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
new file mode 100644
index 0000000..7855763c
--- /dev/null
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2012 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.view;
+
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.content.ComponentCallbacks2;
+import android.content.res.Configuration;
+import android.opengl.ManagedEGLContext;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.util.AndroidRuntimeException;
+import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+
+/**
+ * Provides low-level communication with the system window manager for
+ * operations that are not associated with any particular context.
+ *
+ * This class is only used internally to implement global functions where
+ * the caller already knows the display and relevant compatibility information
+ * for the operation.  For most purposes, you should use {@link WindowManager} instead
+ * since it is bound to a context.
+ *
+ * @see WindowManagerImpl
+ * @hide
+ */
+public final class WindowManagerGlobal {
+    private static final String TAG = "WindowManager";
+
+    /**
+     * The user is navigating with keys (not the touch screen), so
+     * navigational focus should be shown.
+     */
+    public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
+
+    /**
+     * This is the first time the window is being drawn,
+     * so the client must call drawingFinished() when done
+     */
+    public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
+
+    /**
+     * The window manager has changed the surface from the last call.
+     */
+    public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+
+    /**
+     * The window manager is currently animating.  It will call
+     * IWindow.doneAnimating() when done.
+     */
+    public static final int RELAYOUT_RES_ANIMATING = 0x8;
+
+    /**
+     * Flag for relayout: the client will be later giving
+     * internal insets; as a result, the window will not impact other window
+     * layouts until the insets are given.
+     */
+    public static final int RELAYOUT_INSETS_PENDING = 0x1;
+
+    /**
+     * Flag for relayout: the client may be currently using the current surface,
+     * so if it is to be destroyed as a part of the relayout the destroy must
+     * be deferred until later.  The client will call performDeferredDestroy()
+     * when it is okay.
+     */
+    public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
+
+    public static final int ADD_FLAG_APP_VISIBLE = 0x2;
+    public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
+
+    public static final int ADD_OKAY = 0;
+    public static final int ADD_BAD_APP_TOKEN = -1;
+    public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
+    public static final int ADD_NOT_APP_TOKEN = -3;
+    public static final int ADD_APP_EXITING = -4;
+    public static final int ADD_DUPLICATE_ADD = -5;
+    public static final int ADD_STARTING_NOT_NEEDED = -6;
+    public static final int ADD_MULTIPLE_SINGLETON = -7;
+    public static final int ADD_PERMISSION_DENIED = -8;
+
+    private static WindowManagerGlobal sDefaultWindowManager;
+    private static IWindowManager sWindowManagerService;
+    private static IWindowSession sWindowSession;
+
+    private final Object mLock = new Object();
+
+    private View[] mViews;
+    private ViewRootImpl[] mRoots;
+    private WindowManager.LayoutParams[] mParams;
+    private boolean mNeedsEglTerminate;
+
+    private Runnable mSystemPropertyUpdater;
+
+    private WindowManagerGlobal() {
+    }
+
+    public static WindowManagerGlobal getInstance() {
+        synchronized (WindowManagerGlobal.class) {
+            if (sDefaultWindowManager == null) {
+                sDefaultWindowManager = new WindowManagerGlobal();
+            }
+            return sDefaultWindowManager;
+        }
+    }
+
+    public static IWindowManager getWindowManagerService() {
+        synchronized (WindowManagerGlobal.class) {
+            if (sWindowManagerService == null) {
+                sWindowManagerService = IWindowManager.Stub.asInterface(
+                        ServiceManager.getService("window"));
+            }
+            return sWindowManagerService;
+        }
+    }
+
+    public static IWindowSession getWindowSession(Looper mainLooper) {
+        synchronized (WindowManagerGlobal.class) {
+            if (sWindowSession == null) {
+                try {
+                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
+                    IWindowManager windowManager = getWindowManagerService();
+                    sWindowSession = windowManager.openSession(
+                            imm.getClient(), imm.getInputContext());
+                    float animatorScale = windowManager.getAnimationScale(2);
+                    ValueAnimator.setDurationScale(animatorScale);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to open window session", e);
+                }
+            }
+            return sWindowSession;
+        }
+    }
+
+    public static IWindowSession peekWindowSession() {
+        synchronized (WindowManagerGlobal.class) {
+            return sWindowSession;
+        }
+    }
+
+    public void addView(View view, ViewGroup.LayoutParams params,
+            Display display, Window parentWindow) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+        if (display == null) {
+            throw new IllegalArgumentException("display must not be null");
+        }
+        if (!(params instanceof WindowManager.LayoutParams)) {
+            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+        }
+
+        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+        if (parentWindow != null) {
+            parentWindow.adjustLayoutParamsForSubWindow(wparams);
+        }
+
+        ViewRootImpl root;
+        View panelParentView = null;
+
+        synchronized (mLock) {
+            // Start watching for system property changes.
+            if (mSystemPropertyUpdater == null) {
+                mSystemPropertyUpdater = new Runnable() {
+                    @Override public void run() {
+                        synchronized (mLock) {
+                            for (ViewRootImpl root : mRoots) {
+                                root.loadSystemProperties();
+                            }
+                        }
+                    }
+                };
+                SystemProperties.addChangeCallback(mSystemPropertyUpdater);
+            }
+
+            int index = findViewLocked(view, false);
+            if (index >= 0) {
+                throw new IllegalStateException("View " + view
+                        + " has already been added to the window manager.");
+            }
+
+            // If this is a panel window, then find the window it is being
+            // attached to for future reference.
+            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
+                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+                final int count = mViews != null ? mViews.length : 0;
+                for (int i=0; i<count; i++) {
+                    if (mRoots[i].mWindow.asBinder() == wparams.token) {
+                        panelParentView = mViews[i];
+                    }
+                }
+            }
+
+            root = new ViewRootImpl(view.getContext(), display);
+
+            view.setLayoutParams(wparams);
+
+            if (mViews == null) {
+                index = 1;
+                mViews = new View[1];
+                mRoots = new ViewRootImpl[1];
+                mParams = new WindowManager.LayoutParams[1];
+            } else {
+                index = mViews.length + 1;
+                Object[] old = mViews;
+                mViews = new View[index];
+                System.arraycopy(old, 0, mViews, 0, index-1);
+                old = mRoots;
+                mRoots = new ViewRootImpl[index];
+                System.arraycopy(old, 0, mRoots, 0, index-1);
+                old = mParams;
+                mParams = new WindowManager.LayoutParams[index];
+                System.arraycopy(old, 0, mParams, 0, index-1);
+            }
+            index--;
+
+            mViews[index] = view;
+            mRoots[index] = root;
+            mParams[index] = wparams;
+        }
+
+        // do this last because it fires off messages to start doing things
+        root.setView(view, wparams, panelParentView);
+    }
+
+    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+        if (!(params instanceof WindowManager.LayoutParams)) {
+            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+        }
+
+        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
+
+        view.setLayoutParams(wparams);
+
+        synchronized (mLock) {
+            int index = findViewLocked(view, true);
+            ViewRootImpl root = mRoots[index];
+            mParams[index] = wparams;
+            root.setLayoutParams(wparams, false);
+        }
+    }
+
+    public void removeView(View view, boolean immediate) {
+        if (view == null) {
+            throw new IllegalArgumentException("view must not be null");
+        }
+
+        synchronized (mLock) {
+            int index = findViewLocked(view, true);
+            View curView = removeViewLocked(index, immediate);
+            if (curView == view) {
+                return;
+            }
+
+            throw new IllegalStateException("Calling with view " + view
+                    + " but the ViewAncestor is attached to " + curView);
+        }
+    }
+
+    public void closeAll(IBinder token, String who, String what) {
+        synchronized (mLock) {
+            if (mViews == null)
+                return;
+
+            int count = mViews.length;
+            //Log.i("foo", "Closing all windows of " + token);
+            for (int i=0; i<count; i++) {
+                //Log.i("foo", "@ " + i + " token " + mParams[i].token
+                //        + " view " + mRoots[i].getView());
+                if (token == null || mParams[i].token == token) {
+                    ViewRootImpl root = mRoots[i];
+
+                    //Log.i("foo", "Force closing " + root);
+                    if (who != null) {
+                        WindowLeaked leak = new WindowLeaked(
+                                what + " " + who + " has leaked window "
+                                + root.getView() + " that was originally added here");
+                        leak.setStackTrace(root.getLocation().getStackTrace());
+                        Log.e(TAG, leak.getMessage(), leak);
+                    }
+
+                    removeViewLocked(i, false);
+                    i--;
+                    count--;
+                }
+            }
+        }
+    }
+
+    private View removeViewLocked(int index, boolean immediate) {
+        ViewRootImpl root = mRoots[index];
+        View view = root.getView();
+
+        if (view != null) {
+            InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
+            if (imm != null) {
+                imm.windowDismissed(mViews[index].getWindowToken());
+            }
+        }
+        root.die(immediate);
+
+        final int count = mViews.length;
+
+        // remove it from the list
+        View[] tmpViews = new View[count-1];
+        removeItem(tmpViews, mViews, index);
+        mViews = tmpViews;
+
+        ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
+        removeItem(tmpRoots, mRoots, index);
+        mRoots = tmpRoots;
+
+        WindowManager.LayoutParams[] tmpParams
+                = new WindowManager.LayoutParams[count-1];
+        removeItem(tmpParams, mParams, index);
+        mParams = tmpParams;
+
+        if (view != null) {
+            view.assignParent(null);
+            // func doesn't allow null...  does it matter if we clear them?
+            //view.setLayoutParams(null);
+        }
+        return view;
+    }
+
+    private static void removeItem(Object[] dst, Object[] src, int index) {
+        if (dst.length > 0) {
+            if (index > 0) {
+                System.arraycopy(src, 0, dst, 0, index);
+            }
+            if (index < dst.length) {
+                System.arraycopy(src, index+1, dst, index, src.length-index-1);
+            }
+        }
+    }
+
+    private int findViewLocked(View view, boolean required) {
+        synchronized (mLock) {
+            if (mViews != null) {
+                final int count = mViews.length;
+                for (int i = 0; i < count; i++) {
+                    if (mViews[i] == view) {
+                        return i;
+                    }
+                }
+            }
+            if (required) {
+                throw new IllegalArgumentException("View not attached to window manager");
+            }
+            return -1;
+        }
+    }
+
+    public void startTrimMemory(int level) {
+        if (HardwareRenderer.isAvailable()) {
+            // On low-end gfx devices we trim when memory is moderate;
+            // on high-end devices we do this when low.
+            if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
+                    || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
+                            && !ActivityManager.isHighEndGfx())) {
+                // Destroy all hardware surfaces and resources associated to
+                // known windows
+                synchronized (mLock) {
+                    if (mViews == null) return;
+                    int count = mViews.length;
+                    for (int i = 0; i < count; i++) {
+                        mRoots[i].terminateHardwareResources();
+                    }
+                }
+                // Force a full memory flush
+                mNeedsEglTerminate = true;
+                HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
+                return;
+            }
+
+            HardwareRenderer.startTrimMemory(level);
+        }
+    }
+
+    public void endTrimMemory() {
+        HardwareRenderer.endTrimMemory();
+
+        if (mNeedsEglTerminate) {
+            ManagedEGLContext.doTerminate();
+            mNeedsEglTerminate = false;
+        }
+    }
+
+    public void trimLocalMemory() {
+        synchronized (mLock) {
+            if (mViews == null) return;
+            int count = mViews.length;
+            for (int i = 0; i < count; i++) {
+                mRoots[i].destroyHardwareLayers();
+            }
+        }
+    }
+
+    public void dumpGfxInfo(FileDescriptor fd) {
+        FileOutputStream fout = new FileOutputStream(fd);
+        PrintWriter pw = new PrintWriter(fout);
+        try {
+            synchronized (mLock) {
+                if (mViews != null) {
+                    final int count = mViews.length;
+
+                    pw.println("Profile data in ms:");
+
+                    for (int i = 0; i < count; i++) {
+                        ViewRootImpl root = mRoots[i];
+                        String name = getWindowName(root);
+                        pw.printf("\n\t%s", name);
+
+                        HardwareRenderer renderer =
+                                root.getView().mAttachInfo.mHardwareRenderer;
+                        if (renderer != null) {
+                            renderer.dumpGfxInfo(pw);
+                        }
+                    }
+
+                    pw.println("\nView hierarchy:\n");
+
+                    int viewsCount = 0;
+                    int displayListsSize = 0;
+                    int[] info = new int[2];
+
+                    for (int i = 0; i < count; i++) {
+                        ViewRootImpl root = mRoots[i];
+                        root.dumpGfxInfo(info);
+
+                        String name = getWindowName(root);
+                        pw.printf("  %s\n  %d views, %.2f kB of display lists",
+                                name, info[0], info[1] / 1024.0f);
+                        HardwareRenderer renderer =
+                                root.getView().mAttachInfo.mHardwareRenderer;
+                        if (renderer != null) {
+                            pw.printf(", %d frames rendered", renderer.getFrameCount());
+                        }
+                        pw.printf("\n\n");
+
+                        viewsCount += info[0];
+                        displayListsSize += info[1];
+                    }
+
+                    pw.printf("\nTotal ViewRootImpl: %d\n", count);
+                    pw.printf("Total Views:        %d\n", viewsCount);
+                    pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);
+                }
+            }
+        } finally {
+            pw.flush();
+        }
+    }
+
+    private static String getWindowName(ViewRootImpl root) {
+        return root.mWindowAttributes.getTitle() + "/" +
+                root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
+    }
+
+    public void setStoppedState(IBinder token, boolean stopped) {
+        synchronized (mLock) {
+            if (mViews != null) {
+                int count = mViews.length;
+                for (int i=0; i < count; i++) {
+                    if (token == null || mParams[i].token == token) {
+                        ViewRootImpl root = mRoots[i];
+                        root.setStopped(stopped);
+                    }
+                }
+            }
+        }
+    }
+
+    public void reportNewConfiguration(Configuration config) {
+        synchronized (mLock) {
+            if (mViews != null) {
+                int count = mViews.length;
+                config = new Configuration(config);
+                for (int i=0; i < count; i++) {
+                    ViewRootImpl root = mRoots[i];
+                    root.requestUpdateConfiguration(config);
+                }
+            }
+        }
+    }
+}
+
+final class WindowLeaked extends AndroidRuntimeException {
+    public WindowLeaked(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index bd95cdb..bf061df 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,34 +16,20 @@
 
 package android.view;
 
-import android.app.ActivityManager;
-import android.content.ComponentCallbacks2;
-import android.content.res.Configuration;
-import android.opengl.ManagedEGLContext;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.util.AndroidRuntimeException;
-import android.util.Log;
-import android.view.inputmethod.InputMethodManager;
-
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-
-final class WindowLeaked extends AndroidRuntimeException {
-    public WindowLeaked(String msg) {
-        super(msg);
-    }
-}
+import android.content.Context;
+import android.hardware.display.DisplayManager;
 
 /**
- * Low-level communication with the global system window manager.  It implements
- * the ViewManager interface, allowing you to add any View subclass as a
- * top-level window on the screen. Additional window manager specific layout
- * parameters are defined for control over how windows are displayed.
- * It also implements the WindowManager interface, allowing you to control the
- * displays attached to the device.
+ * Provides low-level communication with the system window manager for
+ * operations that are bound to a particular context, display or parent window.
+ * Instances of this object are sensitive to the compatibility info associated
+ * with the running application.
+ *
+ * This object implements the {@link ViewManager} interface,
+ * allowing you to add any View subclass as a top-level window on the screen.
+ * Additional window manager specific layout parameters are defined for
+ * control over how windows are displayed.  It also implements the {@link WindowManager}
+ * interface, allowing you to control the displays attached to the device.
  * 
  * <p>Applications will not normally use WindowManager directly, instead relying
  * on the higher-level facilities in {@link android.app.Activity} and
@@ -51,531 +37,58 @@
  * 
  * <p>Even for low-level window manager access, it is almost never correct to use
  * this class.  For example, {@link android.app.Activity#getWindowManager}
- * provides a ViewManager for adding windows that are associated with that
+ * provides a window manager for adding windows that are associated with that
  * activity -- the window manager will not normally allow you to add arbitrary
  * windows that are not associated with an activity.
- * 
+ *
+ * @see WindowManager
+ * @see WindowManagerGlobal
  * @hide
  */
-public class WindowManagerImpl implements WindowManager {
-    private static final String TAG = "WindowManager";
-
-    /**
-     * The user is navigating with keys (not the touch screen), so
-     * navigational focus should be shown.
-     */
-    public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1;
-
-    /**
-     * This is the first time the window is being drawn,
-     * so the client must call drawingFinished() when done
-     */
-    public static final int RELAYOUT_RES_FIRST_TIME = 0x2;
-
-    /**
-     * The window manager has changed the surface from the last call.
-     */
-    public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
-
-    /**
-     * The window manager is currently animating.  It will call
-     * IWindow.doneAnimating() when done.
-     */
-    public static final int RELAYOUT_RES_ANIMATING = 0x8;
-
-    /**
-     * Flag for relayout: the client will be later giving
-     * internal insets; as a result, the window will not impact other window
-     * layouts until the insets are given.
-     */
-    public static final int RELAYOUT_INSETS_PENDING = 0x1;
-
-    /**
-     * Flag for relayout: the client may be currently using the current surface,
-     * so if it is to be destroyed as a part of the relayout the destroy must
-     * be deferred until later.  The client will call performDeferredDestroy()
-     * when it is okay.
-     */
-    public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2;
-
-    public static final int ADD_FLAG_APP_VISIBLE = 0x2;
-    public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
-    
-    public static final int ADD_OKAY = 0;
-    public static final int ADD_BAD_APP_TOKEN = -1;
-    public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
-    public static final int ADD_NOT_APP_TOKEN = -3;
-    public static final int ADD_APP_EXITING = -4;
-    public static final int ADD_DUPLICATE_ADD = -5;
-    public static final int ADD_STARTING_NOT_NEEDED = -6;
-    public static final int ADD_MULTIPLE_SINGLETON = -7;
-    public static final int ADD_PERMISSION_DENIED = -8;
-
-    private static WindowManagerImpl sDefaultWindowManager;
-    private static IWindowManager sWindowManagerService;
-
-    private final WindowManagerState mState;
+public final class WindowManagerImpl implements WindowManager {
+    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
+    private final Context mContext;
+    private final Display mDisplay;
     private final Window mParentWindow;
-    private final CompatibilityInfoHolder mCompatibilityInfo;
-    private final Display mDefaultDisplay;
 
-    private WindowManagerImpl(WindowManagerState state, Window parentWindow,
-            CompatibilityInfoHolder compatibilityInfo) {
-        mState = state;
+    public WindowManagerImpl(Context context, int displayId) {
+        mContext = context;
+        mDisplay = DisplayManager.getInstance().getDisplay(displayId, mContext);
+        mParentWindow = null;
+    }
+
+    private WindowManagerImpl(Context context, Display display, Window parentWindow) {
+        mContext = context;
+        mDisplay = display;
         mParentWindow = parentWindow;
-        mCompatibilityInfo = compatibilityInfo;
-        mDefaultDisplay = mState.getDefaultDisplay(mCompatibilityInfo);
     }
 
-    public static WindowManagerImpl getDefault() {
-        synchronized (WindowManagerImpl.class) {
-            if (sDefaultWindowManager == null) {
-                sDefaultWindowManager = new WindowManagerImpl(
-                        new WindowManagerState(), null, null);
-            }
-            return sDefaultWindowManager;
-        }
-    }
-
-    public static IWindowManager getWindowManagerService() {
-        synchronized (WindowManagerImpl.class) {
-            if (sWindowManagerService == null) {
-                sWindowManagerService = IWindowManager.Stub.asInterface(
-                        ServiceManager.getService("window"));
-            }
-            return sWindowManagerService;
-        }
-    }
-
-    public WindowManagerImpl makeLocal(Window parentWindow) {
-        return new WindowManagerImpl(mState, parentWindow, parentWindow.getCompatibilityInfo());
-    }
-
-    public WindowManagerImpl makeCompatible(CompatibilityInfoHolder compatInfo) {
-        if (compatInfo == mCompatibilityInfo) {
-            return this;
-        }
-        if (compatInfo == null && mParentWindow == null) {
-            return getDefault();
-        }
-        return new WindowManagerImpl(mState, mParentWindow, compatInfo);
+    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
+        return new WindowManagerImpl(mContext, mDisplay, parentWindow);
     }
 
     @Override
     public void addView(View view, ViewGroup.LayoutParams params) {
-        mState.addView(view, params, mParentWindow, mCompatibilityInfo);
+        mGlobal.addView(view, params, mDisplay, mParentWindow);
     }
 
     @Override
     public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
-        mState.updateViewLayout(view, params);
+        mGlobal.updateViewLayout(view, params);
     }
 
     @Override
     public void removeView(View view) {
-        mState.removeView(view, false);
+        mGlobal.removeView(view, false);
     }
 
     @Override
     public void removeViewImmediate(View view) {
-        mState.removeView(view, true);
+        mGlobal.removeView(view, true);
     }
 
     @Override
     public Display getDefaultDisplay() {
-        return mDefaultDisplay;
-    }
-
-    public void closeAll(IBinder token, String who, String what) {
-        mState.closeAll(token, who, what);
-    }
-
-    public void startTrimMemory(int level) {
-        mState.startTrimMemory(level);
-    }
-
-    public void endTrimMemory() {
-        mState.endTrimMemory();
-    }
-
-    public void trimLocalMemory() {
-        mState.trimLocalMemory();
-    }
-
-    public void dumpGfxInfo(FileDescriptor fd) {
-        mState.dumpGfxInfo(fd);
-    }
-
-    public void setStoppedState(IBinder token, boolean stopped) {
-        mState.setStoppedState(token, stopped);
-    }
-
-    public void reportNewConfiguration(Configuration config) {
-        mState.reportNewConfiguration(config);
-    }
-
-    static final class WindowManagerState {
-        private final Display mDefaultDisplay;
-
-        private View[] mViews;
-        private ViewRootImpl[] mRoots;
-        private WindowManager.LayoutParams[] mParams;
-        private boolean mNeedsEglTerminate;
-
-        private Runnable mSystemPropertyUpdater;
-
-        public WindowManagerState() {
-            mDefaultDisplay = new Display(Display.DEFAULT_DISPLAY, null);
-        }
-
-        public Display getDefaultDisplay(CompatibilityInfoHolder compatInfo) {
-            if (compatInfo == null) {
-                return mDefaultDisplay;
-            }
-            return new Display(Display.DEFAULT_DISPLAY, compatInfo);
-        }
-
-        public void addView(View view, ViewGroup.LayoutParams params, Window parentWindow,
-                CompatibilityInfoHolder cih) {
-            if (!(params instanceof WindowManager.LayoutParams)) {
-                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
-            }
-
-            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
-            if (parentWindow != null) {
-                parentWindow.adjustLayoutParamsForSubWindow(wparams);
-            }
-
-            ViewRootImpl root;
-            View panelParentView = null;
-
-            synchronized (this) {
-                // Start watching for system property changes.
-                if (mSystemPropertyUpdater == null) {
-                    mSystemPropertyUpdater = new Runnable() {
-                        @Override public void run() {
-                            synchronized (this) {
-                                synchronized (this) {
-                                    for (ViewRootImpl root : mRoots) {
-                                        root.loadSystemProperties();
-                                    }
-                                }
-                            }
-                        }
-                    };
-                    SystemProperties.addChangeCallback(mSystemPropertyUpdater);
-                }
-
-                int index = findViewLocked(view, false);
-                if (index >= 0) {
-                    throw new IllegalStateException("View " + view
-                            + " has already been added to the window manager.");
-                }
-
-                // If this is a panel window, then find the window it is being
-                // attached to for future reference.
-                if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
-                        wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
-                    final int count = mViews != null ? mViews.length : 0;
-                    for (int i=0; i<count; i++) {
-                        if (mRoots[i].mWindow.asBinder() == wparams.token) {
-                            panelParentView = mViews[i];
-                        }
-                    }
-                }
-
-                root = new ViewRootImpl(view.getContext());
-                if (cih == null) {
-                    root.mCompatibilityInfo = new CompatibilityInfoHolder();
-                } else {
-                    root.mCompatibilityInfo = cih;
-                }
-
-                view.setLayoutParams(wparams);
-
-                if (mViews == null) {
-                    index = 1;
-                    mViews = new View[1];
-                    mRoots = new ViewRootImpl[1];
-                    mParams = new WindowManager.LayoutParams[1];
-                } else {
-                    index = mViews.length + 1;
-                    Object[] old = mViews;
-                    mViews = new View[index];
-                    System.arraycopy(old, 0, mViews, 0, index-1);
-                    old = mRoots;
-                    mRoots = new ViewRootImpl[index];
-                    System.arraycopy(old, 0, mRoots, 0, index-1);
-                    old = mParams;
-                    mParams = new WindowManager.LayoutParams[index];
-                    System.arraycopy(old, 0, mParams, 0, index-1);
-                }
-                index--;
-
-                mViews[index] = view;
-                mRoots[index] = root;
-                mParams[index] = wparams;
-            }
-
-            // do this last because it fires off messages to start doing things
-            root.setView(view, wparams, panelParentView);
-        }
-
-        public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
-            if (!(params instanceof WindowManager.LayoutParams)) {
-                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
-            }
-
-            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
-
-            view.setLayoutParams(wparams);
-
-            synchronized (this) {
-                int index = findViewLocked(view, true);
-                ViewRootImpl root = mRoots[index];
-                mParams[index] = wparams;
-                root.setLayoutParams(wparams, false);
-            }
-        }
-
-        public void removeView(View view, boolean immediate) {
-            synchronized (this) {
-                int index = findViewLocked(view, true);
-                View curView = removeViewLocked(index, immediate);
-                if (curView == view) {
-                    return;
-                }
-
-                throw new IllegalStateException("Calling with view " + view
-                        + " but the ViewAncestor is attached to " + curView);
-            }
-        }
-
-        public void closeAll(IBinder token, String who, String what) {
-            synchronized (this) {
-                if (mViews == null)
-                    return;
-
-                int count = mViews.length;
-                //Log.i("foo", "Closing all windows of " + token);
-                for (int i=0; i<count; i++) {
-                    //Log.i("foo", "@ " + i + " token " + mParams[i].token
-                    //        + " view " + mRoots[i].getView());
-                    if (token == null || mParams[i].token == token) {
-                        ViewRootImpl root = mRoots[i];
-
-                        //Log.i("foo", "Force closing " + root);
-                        if (who != null) {
-                            WindowLeaked leak = new WindowLeaked(
-                                    what + " " + who + " has leaked window "
-                                    + root.getView() + " that was originally added here");
-                            leak.setStackTrace(root.getLocation().getStackTrace());
-                            Log.e(TAG, leak.getMessage(), leak);
-                        }
-
-                        removeViewLocked(i, false);
-                        i--;
-                        count--;
-                    }
-                }
-            }
-        }
-
-        private View removeViewLocked(int index, boolean immediate) {
-            ViewRootImpl root = mRoots[index];
-            View view = root.getView();
-
-            if (view != null) {
-                InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
-                if (imm != null) {
-                    imm.windowDismissed(mViews[index].getWindowToken());
-                }
-            }
-            root.die(immediate);
-
-            final int count = mViews.length;
-
-            // remove it from the list
-            View[] tmpViews = new View[count-1];
-            removeItem(tmpViews, mViews, index);
-            mViews = tmpViews;
-
-            ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1];
-            removeItem(tmpRoots, mRoots, index);
-            mRoots = tmpRoots;
-
-            WindowManager.LayoutParams[] tmpParams
-                    = new WindowManager.LayoutParams[count-1];
-            removeItem(tmpParams, mParams, index);
-            mParams = tmpParams;
-
-            if (view != null) {
-                view.assignParent(null);
-                // func doesn't allow null...  does it matter if we clear them?
-                //view.setLayoutParams(null);
-            }
-            return view;
-        }
-
-        private static void removeItem(Object[] dst, Object[] src, int index) {
-            if (dst.length > 0) {
-                if (index > 0) {
-                    System.arraycopy(src, 0, dst, 0, index);
-                }
-                if (index < dst.length) {
-                    System.arraycopy(src, index+1, dst, index, src.length-index-1);
-                }
-            }
-        }
-
-        private int findViewLocked(View view, boolean required) {
-            synchronized (this) {
-                if (mViews != null) {
-                    final int count = mViews.length;
-                    for (int i = 0; i < count; i++) {
-                        if (mViews[i] == view) {
-                            return i;
-                        }
-                    }
-                }
-                if (required) {
-                    throw new IllegalArgumentException("View not attached to window manager");
-                }
-                return -1;
-            }
-        }
-
-        public void startTrimMemory(int level) {
-            if (HardwareRenderer.isAvailable()) {
-                // On low-end gfx devices we trim when memory is moderate;
-                // on high-end devices we do this when low.
-                if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
-                        || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
-                                && !ActivityManager.isHighEndGfx(mDefaultDisplay))) {
-                    // Destroy all hardware surfaces and resources associated to
-                    // known windows
-                    synchronized (this) {
-                        if (mViews == null) return;
-                        int count = mViews.length;
-                        for (int i = 0; i < count; i++) {
-                            mRoots[i].terminateHardwareResources();
-                        }
-                    }
-                    // Force a full memory flush
-                    mNeedsEglTerminate = true;
-                    HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-                    return;
-                }
-
-                HardwareRenderer.startTrimMemory(level);
-            }
-        }
-
-        public void endTrimMemory() {
-            HardwareRenderer.endTrimMemory();
-
-            if (mNeedsEglTerminate) {
-                ManagedEGLContext.doTerminate();
-                mNeedsEglTerminate = false;
-            }
-        }
-
-        public void trimLocalMemory() {
-            synchronized (this) {
-                if (mViews == null) return;
-                int count = mViews.length;
-                for (int i = 0; i < count; i++) {
-                    mRoots[i].destroyHardwareLayers();
-                }
-            }
-        }
-
-        public void dumpGfxInfo(FileDescriptor fd) {
-            FileOutputStream fout = new FileOutputStream(fd);
-            PrintWriter pw = new PrintWriter(fout);
-            try {
-                synchronized (this) {
-                    if (mViews != null) {
-                        final int count = mViews.length;
-
-                        pw.println("Profile data in ms:");
-
-                        for (int i = 0; i < count; i++) {
-                            ViewRootImpl root = mRoots[i];
-                            String name = getWindowName(root);
-                            pw.printf("\n\t%s", name);
-
-                            HardwareRenderer renderer =
-                                    root.getView().mAttachInfo.mHardwareRenderer;
-                            if (renderer != null) {
-                                renderer.dumpGfxInfo(pw);
-                            }
-                        }
-
-                        pw.println("\nView hierarchy:\n");
-
-                        int viewsCount = 0;
-                        int displayListsSize = 0;
-                        int[] info = new int[2];
-
-                        for (int i = 0; i < count; i++) {
-                            ViewRootImpl root = mRoots[i];
-                            root.dumpGfxInfo(info);
-
-                            String name = getWindowName(root);
-                            pw.printf("  %s\n  %d views, %.2f kB of display lists",
-                                    name, info[0], info[1] / 1024.0f);
-                            HardwareRenderer renderer =
-                                    root.getView().mAttachInfo.mHardwareRenderer;
-                            if (renderer != null) {
-                                pw.printf(", %d frames rendered", renderer.getFrameCount());
-                            }
-                            pw.printf("\n\n");
-
-                            viewsCount += info[0];
-                            displayListsSize += info[1];
-                        }
-
-                        pw.printf("\nTotal ViewRootImpl: %d\n", count);
-                        pw.printf("Total Views:        %d\n", viewsCount);
-                        pw.printf("Total DisplayList:  %.2f kB\n\n", displayListsSize / 1024.0f);
-                    }
-                }
-            } finally {
-                pw.flush();
-            }
-        }
-
-        private static String getWindowName(ViewRootImpl root) {
-            return root.mWindowAttributes.getTitle() + "/" +
-                    root.getClass().getName() + '@' + Integer.toHexString(root.hashCode());
-        }
-
-        public void setStoppedState(IBinder token, boolean stopped) {
-            synchronized (this) {
-                if (mViews != null) {
-                    int count = mViews.length;
-                    for (int i=0; i < count; i++) {
-                        if (token == null || mParams[i].token == token) {
-                            ViewRootImpl root = mRoots[i];
-                            root.setStopped(stopped);
-                        }
-                    }
-                }
-            }
-        }
-
-        public void reportNewConfiguration(Configuration config) {
-            synchronized (this) {
-                if (mViews != null) {
-                    int count = mViews.length;
-                    config = new Configuration(config);
-                    for (int i=0; i < count; i++) {
-                        ViewRootImpl root = mRoots[i];
-                        root.requestUpdateConfiguration(config);
-                    }
-                }
-            }
-        }
+        return mDisplay;
     }
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 7aa3bb4..7173d1d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -390,8 +390,8 @@
          */
         public void switchKeyboardLayout(int deviceId, int direction);
 
-        public void shutdown();
-        public void rebootSafeMode();
+        public void shutdown(boolean confirm);
+        public void rebootSafeMode(boolean confirm);
     }
 
     /**
@@ -487,9 +487,9 @@
      * 
      * @param attrs The window's LayoutParams. 
      *  
-     * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed;
+     * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed;
      *      else an error code, usually
-     *      {@link WindowManagerImpl#ADD_PERMISSION_DENIED}, to abort the add.
+     *      {@link WindowManagerGlobal#ADD_PERMISSION_DENIED}, to abort the add.
      */
     public int checkAddPermission(WindowManager.LayoutParams attrs);
 
@@ -662,7 +662,7 @@
      * @param win The window being added.
      * @param attrs The window's LayoutParams. 
      *  
-     * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed, else an 
+     * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed, else an
      *         error code to abort the add.
      */
     public int prepareAddWindowLw(WindowState win,
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 193e98d..074f910 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.content.Context;
 import android.os.Message;
 import android.os.Build;
 
@@ -1226,6 +1227,18 @@
     }
 
     /**
+     * Returns the default User-Agent used by a WebView.
+     * An instance of WebView could use a different User-Agent if a call
+     * is made to {@link WebSettings#setUserAgent(int)} or
+     * {@link WebSettings#setUserAgentString(String)}.
+     *
+     * @param context a Context object used to access application assets
+     */
+    public static String getDefaultUserAgent(Context context) {
+        return WebView.getFactory().getDefaultUserAgent(context);
+    }
+
+    /**
      * Tells the WebView whether it needs to set a node to have focus when
      * {@link WebView#requestFocus(int, android.graphics.Rect)} is called. The
      * default value is true.
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 66651f7..eac1141 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -374,6 +374,21 @@
         synchronized(sLockForLocaleSettings) {
             locale = sLocale;
         }
+        return getDefaultUserAgentForLocale(mContext, locale);
+    }
+
+    /**
+     * Returns the default User-Agent used by a WebView.
+     * An instance of WebView could use a different User-Agent if a call
+     * is made to {@link WebSettings#setUserAgent(int)} or
+     * {@link WebSettings#setUserAgentString(String)}.
+     *
+     * @param context a Context object used to access application assets
+     * @param locale The Locale to use in the User-Agent string.
+     * @see WebViewFactoryProvider#getDefaultUserAgent(Context)
+     * @see WebView#getDefaultUserAgent(Context)
+     */
+    public static String getDefaultUserAgentForLocale(Context context, Locale locale) {
         StringBuffer buffer = new StringBuffer();
         // Add version
         final String version = Build.VERSION.RELEASE;
@@ -417,9 +432,9 @@
             buffer.append(" Build/");
             buffer.append(id);
         }
-        String mobile = mContext.getResources().getText(
+        String mobile = context.getResources().getText(
             com.android.internal.R.string.web_user_agent_target_content).toString();
-        final String base = mContext.getResources().getText(
+        final String base = context.getResources().getText(
                 com.android.internal.R.string.web_user_agent).toString();
         return String.format(base, buffer, mobile);
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 436762d..4c5699b 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1821,7 +1821,7 @@
         }
     }
 
-    private static synchronized WebViewFactoryProvider getFactory() {
+    static synchronized WebViewFactoryProvider getFactory() {
         // For now the main purpose of this function (and the factory abstration) is to keep
         // us honest and minimize usage of WebViewClassic internals when binding the proxy.
         checkThread();
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 8d79492..9df4852 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -132,6 +132,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
@@ -1308,6 +1309,12 @@
         public WebViewDatabase getWebViewDatabase(Context context) {
             return WebViewDatabaseClassic.getInstance(context);
         }
+
+        @Override
+        public String getDefaultUserAgent(Context context) {
+            return WebSettingsClassic.getDefaultUserAgentForLocale(context,
+                    Locale.getDefault());
+        }
     }
 
     private void onHandleUiEvent(MotionEvent event, int eventType, int flags) {
@@ -6441,9 +6448,13 @@
                                 mWebViewPrivate.getVerticalScrollFactor());
                         final int hdelta = (int) (hscroll *
                                 mWebViewPrivate.getHorizontalScrollFactor());
-                        if (pinScrollBy(hdelta, vdelta, false, 0)) {
-                            return true;
-                        }
+
+                        abortAnimation();
+                        int oldTouchMode = mTouchMode;
+                        startScrollingLayer(event.getX(), event.getY());
+                        doDrag(hdelta, vdelta);
+                        mTouchMode = oldTouchMode;
+                        return true;
                     }
                 }
             }
@@ -7279,11 +7290,7 @@
                     // nativeCreate sets mNativeClass to a non-zero value
                     String drawableDir = BrowserFrame.getRawResFilename(
                             BrowserFrame.DRAWABLEDIR, mContext);
-                    WindowManager windowManager =
-                            (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-                    Display display = windowManager.getDefaultDisplay();
-                    nativeCreate(msg.arg1, drawableDir,
-                            ActivityManager.isHighEndGfx(display));
+                    nativeCreate(msg.arg1, drawableDir, ActivityManager.isHighEndGfx());
                     if (mDelaySetPicture != null) {
                         setNewPicture(mDelaySetPicture, true);
                         mDelaySetPicture = null;
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 1d302f1..b1d42aa 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -93,4 +93,14 @@
      * @return the singleton WebViewDatabase instance
      */
     WebViewDatabase getWebViewDatabase(Context context);
+
+    /**
+     * Returns the default User-Agent used by a WebView.
+     * An instance of WebView could use a different User-Agent if a call
+     * is made to {@link WebSettings#setUserAgent(int)} or
+     * {@link WebSettings#setUserAgentString(String)}.
+     *
+     * @param context a Context object used to access application assets
+     */
+    String getDefaultUserAgent(Context context);
 }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index dd05a03..dcf90e9 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -61,9 +61,9 @@
  * the content of the inflated hierarchy.
  */
 public class RemoteViews implements Parcelable, Filter {
-    
+
     private static final String LOG_TAG = "RemoteViews";
-    
+
     /**
      * The intent extra that contains the appWidgetId.
      * @hide
@@ -71,11 +71,11 @@
     static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId";
 
     /**
-     * The package name of the package containing the layout 
+     * The package name of the package containing the layout
      * resource. (Added to the parcel)
      */
     private final String mPackage;
-    
+
     /**
      * The resource ID of the layout file. (Added to the parcel)
      */
@@ -86,7 +86,7 @@
      * inflated
      */
     private ArrayList<Action> mActions;
-    
+
     /**
      * A class to keep track of memory usage by this RemoteViews
      */
@@ -522,13 +522,13 @@
                                     .getCompatibilityInfo().applicationScale;
                             final int[] pos = new int[2];
                             v.getLocationOnScreen(pos);
-    
+
                             final Rect rect = new Rect();
                             rect.left = (int) (pos[0] * appScale + 0.5f);
                             rect.top = (int) (pos[1] * appScale + 0.5f);
                             rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
                             rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
-    
+
                             final Intent intent = new Intent();
                             intent.setSourceBounds(rect);
                             handler.onClickHandler(v, pendingIntent, intent);
@@ -567,7 +567,7 @@
             this.filterMode = mode;
             this.level = level;
         }
-        
+
         public SetDrawableParameters(Parcel parcel) {
             viewId = parcel.readInt();
             targetBackground = parcel.readInt() != 0;
@@ -581,7 +581,7 @@
             }
             level = parcel.readInt();
         }
-        
+
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(TAG);
             dest.writeInt(viewId);
@@ -596,12 +596,12 @@
             }
             dest.writeInt(level);
         }
-        
+
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
-            
+
             // Pick the correct drawable to modify for this view
             Drawable targetDrawable = null;
             if (targetBackground) {
@@ -610,7 +610,7 @@
                 ImageView imageView = (ImageView) target;
                 targetDrawable = imageView.getDrawable();
             }
-            
+
             if (targetDrawable != null) {
                 // Perform modifications only if values are set correctly
                 if (alpha != -1) {
@@ -634,7 +634,7 @@
 
         public final static int TAG = 3;
     }
-    
+
     private class ReflectionActionWithoutParams extends Action {
         int viewId;
         String methodName;
@@ -938,7 +938,7 @@
                     out.writeString((String)this.value);
                     break;
                 case CHAR_SEQUENCE:
-                    TextUtils.writeToParcel((CharSequence)this.value, out, flags);   
+                    TextUtils.writeToParcel((CharSequence)this.value, out, flags);
                     break;
                 case URI:
                     out.writeInt(this.value != null ? 1 : 0);
@@ -1314,7 +1314,7 @@
     /**
      * Create a new RemoteViews object that will display the views contained
      * in the specified layout file.
-     * 
+     *
      * @param packageName Name of the package that contains the layout resource
      * @param layoutId The id of the layout resource
      */
@@ -1364,7 +1364,7 @@
 
     /**
      * Reads a RemoteViews object from a parcel.
-     * 
+     *
      * @param parcel
      */
     public RemoteViews(Parcel parcel) {
@@ -1547,7 +1547,7 @@
 
     /**
      * Add an action to be executed on the remote side when apply is called.
-     * 
+     *
      * @param a The action to add
      */
     private void addAction(Action a) {
@@ -1619,7 +1619,7 @@
 
     /**
      * Equivalent to calling View.setVisibility
-     * 
+     *
      * @param viewId The id of the view whose visibility should change
      * @param visibility The new visibility for the view
      */
@@ -1629,7 +1629,7 @@
 
     /**
      * Equivalent to calling TextView.setText
-     * 
+     *
      * @param viewId The id of the view whose text should change
      * @param text The new text for the view
      */
@@ -1639,7 +1639,7 @@
 
     /**
      * Equivalent to calling {@link TextView#setTextSize(int, float)}
-     * 
+     *
      * @param viewId The id of the view whose text size should change
      * @param units The units of size (e.g. COMPLEX_UNIT_SP)
      * @param size The size of the text
@@ -1649,33 +1649,29 @@
     }
 
     /**
-     * Equivalent to calling 
+     * Equivalent to calling
      * {@link TextView#setCompoundDrawablesWithIntrinsicBounds(int, int, int, int)}.
      *
      * @param viewId The id of the view whose text should change
      * @param left The id of a drawable to place to the left of the text, or 0
      * @param top The id of a drawable to place above the text, or 0
      * @param right The id of a drawable to place to the right of the text, or 0
-     * @param bottom The id of a drawable to place below the text, or 0 
+     * @param bottom The id of a drawable to place below the text, or 0
      */
     public void setTextViewCompoundDrawables(int viewId, int left, int top, int right, int bottom) {
         addAction(new TextViewDrawableAction(viewId, false, left, top, right, bottom));
     }
 
     /**
-     * Equivalent to calling {@link 
+     * Equivalent to calling {@link
      * TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)}.
      *
      * @param viewId The id of the view whose text should change
-     * @param start The id of a drawable to place before the text (relative to the 
+     * @param start The id of a drawable to place before the text (relative to the
      * layout direction), or 0
      * @param top The id of a drawable to place above the text, or 0
      * @param end The id of a drawable to place after the text, or 0
-<<<<<<< HEAD
-     * @param bottom The id of a drawable to place below the text, or 0 
-=======
      * @param bottom The id of a drawable to place below the text, or 0
->>>>>>> 0a43f67e
      */
     public void setTextViewCompoundDrawablesRelative(int viewId, int start, int top, int end, int bottom) {
         addAction(new TextViewDrawableAction(viewId, true, start, top, end, bottom));
@@ -1683,17 +1679,17 @@
 
     /**
      * Equivalent to calling ImageView.setImageResource
-     * 
+     *
      * @param viewId The id of the view whose drawable should change
      * @param srcId The new resource id for the drawable
      */
-    public void setImageViewResource(int viewId, int srcId) {   
+    public void setImageViewResource(int viewId, int srcId) {
         setInt(viewId, "setImageResource", srcId);
     }
 
     /**
      * Equivalent to calling ImageView.setImageURI
-     * 
+     *
      * @param viewId The id of the view whose drawable should change
      * @param uri The Uri for the image
      */
@@ -1703,7 +1699,7 @@
 
     /**
      * Equivalent to calling ImageView.setImageBitmap
-     * 
+     *
      * @param viewId The id of the view whose bitmap should change
      * @param bitmap The new Bitmap for the drawable
      */
@@ -1726,7 +1722,7 @@
      * {@link Chronometer#setFormat Chronometer.setFormat},
      * and {@link Chronometer#start Chronometer.start()} or
      * {@link Chronometer#stop Chronometer.stop()}.
-     * 
+     *
      * @param viewId The id of the {@link Chronometer} to change
      * @param base The time at which the timer would have read 0:00.  This
      *             time should be based off of
@@ -1740,21 +1736,21 @@
         setString(viewId, "setFormat", format);
         setBoolean(viewId, "setStarted", started);
     }
-    
+
     /**
      * Equivalent to calling {@link ProgressBar#setMax ProgressBar.setMax},
      * {@link ProgressBar#setProgress ProgressBar.setProgress}, and
      * {@link ProgressBar#setIndeterminate ProgressBar.setIndeterminate}
      *
      * If indeterminate is true, then the values for max and progress are ignored.
-     * 
+     *
      * @param viewId The id of the {@link ProgressBar} to change
      * @param max The 100% value for the progress bar
      * @param progress The current value of the progress bar.
-     * @param indeterminate True if the progress bar is indeterminate, 
+     * @param indeterminate True if the progress bar is indeterminate,
      *                false if not.
      */
-    public void setProgressBar(int viewId, int max, int progress, 
+    public void setProgressBar(int viewId, int max, int progress,
             boolean indeterminate) {
         setBoolean(viewId, "setIndeterminate", indeterminate);
         if (!indeterminate) {
@@ -1762,12 +1758,12 @@
             setInt(viewId, "setProgress", progress);
         }
     }
-    
+
     /**
      * Equivalent to calling
      * {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
      * to launch the provided {@link PendingIntent}.
-     * 
+     *
      * When setting the on-click action of items within collections (eg. {@link ListView},
      * {@link StackView} etc.), this method will not work. Instead, use {@link
      * RemoteViews#setPendingIntentTemplate(int, PendingIntent) in conjunction with
@@ -1827,7 +1823,7 @@
      * view.
      * <p>
      * You can omit specific calls by marking their values with null or -1.
-     * 
+     *
      * @param viewId The id of the view that contains the target
      *            {@link Drawable}
      * @param targetBackground If true, apply these parameters to the
@@ -1853,7 +1849,7 @@
 
     /**
      * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}.
-     * 
+     *
      * @param viewId The id of the view whose text color should change
      * @param color Sets the text color for all the states (normal, selected,
      *            focused) to be this color.
@@ -2105,16 +2101,16 @@
     /**
      * Inflates the view hierarchy represented by this object and applies
      * all of the actions.
-     * 
+     *
      * <p><strong>Caller beware: this may throw</strong>
-     * 
+     *
      * @param context Default context to use
      * @param parent Parent that the resulting view hierarchy will be attached to. This method
      * does <strong>not</strong> attach the hierarchy. The caller should do so when appropriate.
      * @return The inflated view hierarchy
      */
     public View apply(Context context, ViewGroup parent) {
-        return apply(context, parent, DEFAULT_ON_CLICK_HANDLER);
+        return apply(context, parent, null);
     }
 
     /** @hide */
@@ -2142,12 +2138,12 @@
      * Applies all of the actions to the provided view.
      *
      * <p><strong>Caller beware: this may throw</strong>
-     * 
+     *
      * @param v The view to apply the actions to.  This should be the result of
      * the {@link #apply(Context,ViewGroup)} call.
      */
     public void reapply(Context context, View v) {
-        reapply(context, v, DEFAULT_ON_CLICK_HANDLER);
+        reapply(context, v, null);
     }
 
     /** @hide */
@@ -2170,6 +2166,7 @@
 
     private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
         if (mActions != null) {
+            handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler;
             final int count = mActions.size();
             for (int i = 0; i < count; i++) {
                 Action a = mActions.get(i);
@@ -2198,7 +2195,7 @@
 
     /* (non-Javadoc)
      * Used to restrict the views which can be inflated
-     * 
+     *
      * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
      */
     public boolean onLoadClass(Class clazz) {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 5d6491d..1f713d4 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -664,7 +664,7 @@
     @Override
     public void setChecked(boolean checked) {
         super.setChecked(checked);
-        setThumbPosition(checked);
+        setThumbPosition(isChecked());
         invalidate();
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5be9899..f502de4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2203,6 +2203,27 @@
     }
 
     /**
+     * Get the default {@link Locale} of the text in this TextView.
+     * @return the default {@link Locale} of the text in this TextView.
+     */
+    public Locale getTextLocale() {
+        return mTextPaint.getTextLocale();
+    }
+
+    /**
+     * Set the default {@link Locale} of the text in this TextView to the given value. This value
+     * is used to choose appropriate typefaces for ambiguous characters. Typically used for CJK
+     * locales to disambiguate Hanzi/Kanji/Hanja characters.
+     *
+     * @param locale the {@link Locale} for drawing text, must not be null.
+     *
+     * @see Paint#setTextLocale
+     */
+    public void setTextLocale(Locale locale) {
+        mTextPaint.setTextLocale(locale);
+    }
+
+    /**
      * @return the size (in pixels) of the default text size in this TextView.
      */
     @ViewDebug.ExportedProperty(category = "text")
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 7dcbc3e..053ade7 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -30,7 +30,6 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
@@ -331,7 +330,7 @@
         View mView;
         View mNextView;
         
-        WindowManagerImpl mWM;
+        WindowManager mWM;
 
         TN() {
             // XXX This should be changed to use a Dialog, with a Theme.Toast
@@ -371,7 +370,7 @@
                 // remove the old view if necessary
                 handleHide();
                 mView = mNextView;
-                mWM = WindowManagerImpl.getDefault();
+                mWM = (WindowManager)mView.getContext().getSystemService(Context.WINDOW_SERVICE);
                 // We can resolve the Gravity here by using the Locale for getting
                 // the layout direction
                 final Configuration config = mView.getContext().getResources().getConfiguration();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index e63c57f..bffbe11 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -150,7 +150,8 @@
 
             resizeGrid();
         } else if (count == 1) {
-            startActivity(mAdapter.intentForPosition(0));
+            startActivityAsUser(mAdapter.intentForPosition(0),
+                    new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
             mPackageMonitor.unregister();
             mRegistered = false;
             finish();
@@ -363,12 +364,12 @@
                     if (r.match > bestMatch) bestMatch = r.match;
                 }
                 getPackageManager().addPreferredActivity(filter, bestMatch, set,
-                        intent.getComponent());
+                        intent.getComponent(), UserHandle.getUserId(mLaunchedFromUid));
             }
         }
 
         if (intent != null) {
-            startActivity(intent);
+            startActivityAsUser(intent, new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
         }
     }
 
@@ -376,7 +377,7 @@
         Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
                 .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
                 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
-        startActivity(in);
+        startActivityAsUser(in, new UserHandle(UserHandle.getUserId(mLaunchedFromUid)));
     }
 
     private final class DisplayResolveInfo {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 6ad67c3..9e43749 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -16,16 +16,17 @@
 
 package com.android.internal.os;
 
+import static libcore.io.OsConstants.S_IRWXG;
+import static libcore.io.OsConstants.S_IRWXO;
+
 import android.content.pm.ActivityInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.net.LocalServerSocket;
 import android.os.Debug;
-import android.os.FileUtils;
 import android.os.Process;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.util.EventLog;
 import android.util.Log;
 
@@ -33,6 +34,7 @@
 import dalvik.system.Zygote;
 
 import libcore.io.IoUtils;
+import libcore.io.Libcore;
 
 import java.io.BufferedReader;
 import java.io.FileDescriptor;
@@ -452,7 +454,7 @@
         closeServerSocket();
 
         // set umask to 0077 so new files and directories will default to owner-only permissions.
-        FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);
+        Libcore.os.umask(S_IRWXG | S_IRWXO);
 
         if (parsedArgs.niceName != null) {
             Process.setArgV0(parsedArgs.niceName);
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index af512a3..98beadb 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -27,6 +27,7 @@
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.Surface;
+import android.view.WindowManagerGlobal;
 
 /**
  * Provides helper functions for configuring the display rotation policy.
@@ -79,8 +80,7 @@
             @Override
             public void run() {
                 try {
-                    IWindowManager wm = IWindowManager.Stub.asInterface(
-                            ServiceManager.getService(Context.WINDOW_SERVICE));
+                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                     if (enabled) {
                         wm.freezeRotation(-1);
                     } else {
@@ -107,8 +107,7 @@
             @Override
             public void run() {
                 try {
-                    IWindowManager wm = IWindowManager.Stub.asInterface(
-                            ServiceManager.getService(Context.WINDOW_SERVICE));
+                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                     if (enabled) {
                         wm.freezeRotation(Surface.ROTATION_0);
                     } else {
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index a65262c..edc97322 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -22,6 +22,7 @@
 #include "jni.h"
 #include "GraphicsJNI.h"
 #include <android_runtime/AndroidRuntime.h>
+#include <ScopedUtfChars.h>
 
 #include "SkBlurDrawLooper.h"
 #include "SkColorFilter.h"
@@ -30,6 +31,7 @@
 #include "SkShader.h"
 #include "SkTypeface.h"
 #include "SkXfermode.h"
+#include "unicode/uloc.h"
 #include "unicode/ushape.h"
 #include "TextLayout.h"
 
@@ -254,11 +256,51 @@
         obj->setTextAlign(align);
     }
 
+    // generate bcp47 identifier for the supplied locale
+    static void toLanguageTag(char* output, size_t outSize,
+            const char* locale) {
+        if (output == NULL || outSize <= 0) {
+            return;
+        }
+        if (locale == NULL) {
+            output[0] = '\0';
+            return;
+        }
+        char canonicalChars[ULOC_FULLNAME_CAPACITY];
+        UErrorCode uErr = U_ZERO_ERROR;
+        uloc_canonicalize(locale, canonicalChars, ULOC_FULLNAME_CAPACITY,
+                &uErr);
+        if (U_SUCCESS(uErr)) {
+            char likelyChars[ULOC_FULLNAME_CAPACITY];
+            uErr = U_ZERO_ERROR;
+            uloc_addLikelySubtags(canonicalChars, likelyChars,
+                    ULOC_FULLNAME_CAPACITY, &uErr);
+            if (U_SUCCESS(uErr)) {
+                uErr = U_ZERO_ERROR;
+                uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
+                if (U_SUCCESS(uErr)) {
+                    return;
+                } else {
+                    ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
+                            u_errorName(uErr));
+                }
+            } else {
+                ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s",
+                        canonicalChars, u_errorName(uErr));
+            }
+        } else {
+            ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale,
+                    u_errorName(uErr));
+        }
+        // unable to build a proper language identifier
+        output[0] = '\0';
+    }
+
     static void setTextLocale(JNIEnv* env, jobject clazz, SkPaint* obj, jstring locale) {
-        const char* localeArray = env->GetStringUTFChars(locale, NULL);
-        SkString skLocale(localeArray);
-        obj->setTextLocale(skLocale);
-        env->ReleaseStringUTFChars(locale, localeArray);
+        ScopedUtfChars localeChars(env, locale);
+        char langTag[ULOC_FULLNAME_CAPACITY];
+        toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
+        obj->setLanguage(SkLanguage(langTag));
     }
 
     static jfloat getTextSize(JNIEnv* env, jobject paint) {
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 9b9b991..7abfcf1 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -19,6 +19,7 @@
 #include "TextLayoutCache.h"
 #include "TextLayout.h"
 #include "SkFontHost.h"
+#include "SkTypeface_android.h"
 #include <unicode/unistr.h>
 #include <unicode/normlzr.h>
 #include <unicode/uchar.h>
@@ -224,7 +225,7 @@
  */
 TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0),
         dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
-        hinting(SkPaint::kNo_Hinting)  {
+        hinting(SkPaint::kNo_Hinting), variant(SkPaint::kDefault_Variant), language()  {
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
@@ -237,6 +238,8 @@
     textScaleX = paint->getTextScaleX();
     flags = paint->getFlags();
     hinting = paint->getHinting();
+    variant = paint->getFontVariant();
+    language = paint->getLanguage();
 }
 
 TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
@@ -251,7 +254,9 @@
         textSkewX(other.textSkewX),
         textScaleX(other.textScaleX),
         flags(other.flags),
-        hinting(other.hinting) {
+        hinting(other.hinting),
+        variant(other.variant),
+        language(other.language) {
     if (other.text) {
         textCopy.setTo(other.text, other.contextCount);
     }
@@ -288,6 +293,12 @@
     deltaInt = lhs.dirFlags - rhs.dirFlags;
     if (deltaInt) return (deltaInt);
 
+    deltaInt = lhs.variant - rhs.variant;
+    if (deltaInt) return (deltaInt);
+
+    if (lhs.language < rhs.language) return -1;
+    if (lhs.language > rhs.language) return +1;
+
     return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
 }
 
@@ -615,6 +626,8 @@
     mShapingPaint.setTextScaleX(paint->getTextScaleX());
     mShapingPaint.setFlags(paint->getFlags());
     mShapingPaint.setHinting(paint->getHinting());
+    mShapingPaint.setFontVariant(paint->getFontVariant());
+    mShapingPaint.setLanguage(paint->getLanguage());
 
     // Split the BiDi run into Script runs. Harfbuzz will populate the pos, length and script
     // into the shaperItem
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index f007f9a..64b33a0 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -32,7 +32,7 @@
 #include <SkTemplates.h>
 #include <SkUtils.h>
 #include <SkAutoKern.h>
-#include "SkTypeface_android.h"
+#include <SkLanguage.h>
 
 #include <unicode/ubidi.h>
 #include <unicode/ushape.h>
@@ -102,6 +102,8 @@
     SkScalar textScaleX;
     uint32_t flags;
     SkPaint::Hinting hinting;
+    SkPaint::FontVariant variant;
+    SkLanguage language;
 
     inline const UChar* getText() const { return text ? text : textCopy.string(); }
 
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index 82bfc36..a07f5b7 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -55,11 +55,6 @@
     return chmod(file8.string(), mode) == 0 ? 0 : errno;
 }
 
-jint android_os_FileUtils_setUMask(JNIEnv* env, jobject clazz, jint mask)
-{
-    return umask(mask);
-}
-
 jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
 {
     if (path == NULL) {
@@ -83,7 +78,6 @@
 
 static const JNINativeMethod methods[] = {
     {"setPermissions",  "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
-    {"setUMask",        "(I)I",                    (void*)android_os_FileUtils_setUMask},
     {"getFatVolumeId",  "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
 };
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 3ad6406..bada329 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -221,7 +221,7 @@
 static void Surface_init(
         JNIEnv* env, jobject clazz,
         jobject session,
-        jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
+        jint, jstring jname, jint layerStack, jint w, jint h, jint format, jint flags)
 {
     if (session == NULL) {
         doThrowNPE(env);
@@ -233,12 +233,12 @@
 
     sp<SurfaceControl> surface;
     if (jname == NULL) {
-        surface = client->createSurface(dpy, w, h, format, flags);
+        surface = client->createSurface(layerStack, w, h, format, flags);
     } else {
         const jchar* str = env->GetStringCritical(jname, 0);
         const String8 name(str, env->GetStringLength(jname));
         env->ReleaseStringCritical(jname, str);
-        surface = client->createSurface(name, dpy, w, h, format, flags);
+        surface = client->createSurface(name, layerStack, w, h, format, flags);
     }
 
     if (surface == 0) {
@@ -717,7 +717,7 @@
     }
 }
 
-static void Surface_setDisplayId(JNIEnv* env, jobject thiz, jint displayId)
+static void Surface_setLayerStack(JNIEnv* env, jobject thiz, jint layerStack)
 {
     const sp<SurfaceControl>& surface(getSurfaceControl(env, thiz));
     if (surface == 0) return;
@@ -863,7 +863,7 @@
     {"writeToParcel",       "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
     {"isConsumerRunningBehind", "()Z", (void*)Surface_isConsumerRunningBehind },
     {"setWindowCrop",       "(Landroid/graphics/Rect;)V", (void*)Surface_setWindowCrop },
-    {"setDisplayId",        "(I)V", (void*)Surface_setDisplayId },
+    {"setLayerStack",        "(I)V", (void*)Surface_setLayerStack },
 };
 
 void nativeClassInit(JNIEnv* env, jclass clazz)
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index db862c8..ad03dd2 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -224,6 +224,10 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Laat die program toe om aksies vir verskillende gebruikers op die toestel uit te voer. Kwaadwillige programme kan dit gebruik om die beskerming tussen gebruikers te skend."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"volle lisensie vir interaksie tussen gebruikers"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Laat alle moontlike interaksies tussen gebruikers toe."</string>
+    <!-- no translation found for permlab_manageUsers (1676150911672282428) -->
+    <skip />
+    <!-- no translation found for permdesc_manageUsers (8409306667645355638) -->
+    <skip />
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"haal besonderhede van lopende programme op"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Laat die program toe om inligting op te haal oor huidige en onlangse lopende take. Kwaadwillige programme kan dalk private inligting oor ander programme ontdek."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"herrangskik lopende programme"</string>
@@ -1309,4 +1313,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-oudio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Klaar"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Media-uitvoer"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ef8f604..fc6d4b8 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"መተግበሪያው በመሣሪያው ላይ በተለያዩ ተጠቃሚዎች ላይ እርምጃዎችን እንዲፈጽም ይፈቅድለታል። ተንኮል-አዘል መተግበሪያዎች ይህንን ተጠቅመው በተጠቃሚዎች መካከል ያለውን ጥበቃ ሊጥሱ ይችላሉ።"</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"በተለያዩ ተጠቃሚዎች መካከል መስተጋብር ለመፍጠር ሙሉ ፍቃድ"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"በተለያዩ ተጠቃሚዎች ላይ ሊኖሩ የሚችሉ መስተጋብሮችን ሁሉ ይፈቅዳል።"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"ተጠቃሚዎችን ያስተዳድሩ"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"መተግበሪያዎች በመሣሪያዎች ላይ ያሉ ተጠቃሚዎችን እንዲያቀናብር ያስችለዋል፣ መጠየቅን፣ መፍጠርንና መሰረዝን ጨምሮ።"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"እየሄዱ ስላሉ የመተግበሪያዎች ዝርዝሮች አምጣ"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"መተግበሪያው በአሁኑ ጊዜ እየተካሄዱ ስላሉና በቅርብ ጊዜ ስለተካሄዱ ተግባሮች መረጃ ዝርዝር እንዲያወጣ ይፈቅድለታል። ተንኮል-አዘል መተግበሪያዎች ስለ ሌሎች መተግበሪያዎች የግል መረጃ ሊያገኙ ይችላሉ።"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"አሂድ ትግበራዎችን ድጋሚ ደርድር"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"የብሉቱዝ ድምጽ"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"ተከናውኗል"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"የሚዲያ ውጽዓት"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"ውስጥ የተሰራ ማያ ገጽ"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 17f4dd1..14d95a5 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"للسماح للتطبيق بتنفيذ إجراءات بين مستخدمين مختلفين على الجهاز. قد تستخدم التطبيقات الضارة ذلك لانتهاك الحماية بين المستخدمين."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"الترخيص بالكامل للتعامل بين المستخدمين"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"للسماح بجميع التعاملات المحتملة بين المستخدمين."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"إدارة المستخدمين"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"لتمكين التطبيقات من إدارة المستخدمين على الجهاز، بما في ذلك طلب البحث والإنشاء والحذف."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"استرداد تفاصيل التطبيقات قيد التشغيل"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"يسمح للتطبيق باسترداد معلومات تفصيلية حول المهام قيد التشغيل حاليًا ومؤخرًا. قد تكتشف التطبيقات الضارة معلومات خاصة حول التطبيقات الأخرى."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"إعادة ترتيب التطبيقات قيد التشغيل"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"صوت بلوتوث"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"تم"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"المنفذ الإعلامي"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index b9b6cf3..d801628 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дазваляе прыкладанню выконваць дзеяннi сярод розных карыстальнiкаў прылады. Шкоднасныя прыкладаннi могуць выкарыстоўваць гэта, каб парушыць абарону памiж карыстальнiкамi."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"поўная ліцэнзія для ўзаемадзеяння паміж карыстальнiкамi"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дазваляе ўсе магчымыя ўзаемадзеяннi паміж карыстальнікамі."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"кіраванне дадзенымi карыстальнікаў"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дазваляе прыкладанням кіраваць звесткамi карыстальнікаў на прыладзе, у тым ліку запытамi, працэсамi стварэння і выдалення."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"атрымаць падрабязныя дадзеныя пра запушчаныя прыкладаннi"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дазваляе прыкладанню атрымліваць падрабязную інфармацыю пра бягучыя і нядаўна запушчаныя задачы. Шкоднасныя прыкладанні могуць атрымліваць асабістую інфармацыю пра іншыя прыкладаннi."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"змяніць парадак запушчаных прыкладанняў"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-аўдыё"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Гатова"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Мультымедыйны выхад"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Убудаваны экран"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 6370ed4..81ba8a7 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Разрешава на приложението да изпълнява действия за различни потребители на устройството. Злонамерените приложения може да използват това, за да нарушат защитата между потребителите."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"пълен лиценз за взаимодействие с потребителите"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Разрешава всички възможни взаимодействия с потребителите."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"управление на потребителите"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Разрешава на приложенията да управляват потребителите на устройството, включително изброяването, създаването и изтриването им."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"извличане на подробности за изпълняваните прилож."</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Разрешава на приложението да извлича подробна информация за задачите, изпълнявани понастоящем и неотдавна. Злонамерените приложения могат да открият поверителна информация за други приложения."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"пренареждане на изпълняваните приложения"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Звук през Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Изходяща мултимедия"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 9c6cca1..0781217 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permet que l\'aplicació dugui a terme accions en diferents usuaris del dispositiu. Les aplicacions malicioses poden fer servir aquest permís per infringir la protecció entre usuaris."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"llicència completa per interaccionar entre usuaris"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permet totes les interaccions possibles entre usuaris."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gestió d\'usuaris"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permet que les aplicacions gestionin usuaris al dispositiu, incloses les consultes, la creació i la supressió."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recupera els detalls d\'aplicacions en execució"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permet que l\'aplicació recuperi informació detallada sobre les tasques que s\'estan executant actualment i que s\'han executat recentment. Les aplicacions malicioses poden descobrir informació privada sobre altres aplicacions."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"canvia l\'ordre de les aplicacions en execució"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Àudio per Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fet"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Sortida de contingut multimèdia"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Pantalla integrada"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 898fe14..4e7da84 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umožňuje aplikaci provádět akce napříč různými uživateli zařízení. Škodlivé aplikace toto oprávnění mohou zneužít k obejití ochrany mezi uživateli."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"úplné oprávnění k interakcím napříč uživateli"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Povoluje všechny možné interakce napříč uživateli."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"správa uživatelů"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Umožňuje aplikacím spravovat uživatele v zařízení, včetně vytváření a mazání dotazů."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"získání podrobností o spuštěných aplikacích"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Umožňuje aplikaci získat podrobné informace o aktuálně a naposledy spuštěných úlohách. Škodlivé aplikace mohou odhalit soukromé informace o ostatních aplikacích."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"změna uspořádání spuštěných aplikací"</string>
@@ -842,7 +844,7 @@
     <item quantity="other" msgid="3903706804349556379">"před <xliff:g id="COUNT">%d</xliff:g> s"</item>
   </plurals>
   <plurals name="num_minutes_ago">
-    <item quantity="one" msgid="3306787433088810191">"před 1 minutou"</item>
+    <item quantity="one" msgid="3306787433088810191">"před 1 min"</item>
     <item quantity="other" msgid="2176942008915455116">"před <xliff:g id="COUNT">%d</xliff:g> min"</item>
   </plurals>
   <plurals name="num_hours_ago">
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth Audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Hotovo"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Výstup médií"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9ccf3f0..ea40879 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillader, at appen udfører handlinger på tværs af forskellige brugere på enheden. Ondsindede apps kan bruge dette til at krænke beskyttelsen mellem brugere."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"fuld licens til at kommunikere på tværs af brugere"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillader alle mulige former for kommunikation på tværs af brugere."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"administrer brugere"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Tillader, at apps administrerer brugere på enheden, herunder forespørgsler, oprettelser og sletninger."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hente oplysninger om apps, der kører"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillader, at appen kan hente oplysninger om aktuelle og seneste opgaver. Ondsindede apps kan muligvis finde personlige oplysninger om andre apps."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"omorganisere kørende apps"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Udfør"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieudgang"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Indbygget skærm"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f72d625..a0280c8 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ermöglicht der App, auf dem Gerät nutzerübergreifend Aktionen durchzuführen. Schädliche Apps können so den zwischen den Nutzern bestehenden Schutz aufheben."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"Vollständige Lizenz zum nutzerübergreifenden Interagieren"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ermöglicht alle möglichen nutzerübergreifenden Interaktionen"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Nutzer verwalten"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ermöglicht Apps die Verwaltung der Nutzer auf dem Gerät, unter anderem das Abfragen, Erstellen und Löschen von Nutzern"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Details zu ausgeführten Apps abrufen"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ermöglicht der App, detaillierte Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Schädliche Apps können so geheime Informationen zu anderen Apps erhalten."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"Aktive Apps neu ordnen"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-Audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fertig"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Medienausgabe"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Integrierter Bildschirm"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 95717a2..82f0c62 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Δίνει στην εφαρμογή τη δυνατότητα να πραγματοποιεί ενέργειες σε όλους τους διαφορετικούς χρήστες στη συσκευή. Οι κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτή τη δυνατότητα για να παραβιάσουν την προστασία μεταξύ των χρηστών."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"πλήρης άδεια αλληλεπίδρασης στους χρήστες"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Επιτρέπει όλες τις πιθανές αλληλεπιδράσεις στους χρήστες."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"διαχείριση χρηστών"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Επιτρέπει στις εφαρμογές να διαχειρίζονται τους χρήστες της συσκευής, συμπεριλαμβανομένων των ερωτημάτων της δημιουργίας και της διαγραφής."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"ανάκτηση λεπτομερειών σχετικά με τις εκτελούμενες εφαρμογές"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Επιτρέπει στην εφαρμογή την ανάκτηση λεπτομερών πληροφοριών σχετικά με τις τρέχουσες εκτελούμενες εργασίες και τις εργασίες που έχουν εκτελεστεί πρόσφατα. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακαλύψουν ιδιωτικές πληροφορίες σχετικά με άλλες εφαρμογές."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"αναδιάταξη εκτελούμενων εφαρμογών"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Ήχος Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Τέλος"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Έξοδος μέσων"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Ενσωματωμένη οθόνη"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index eaa3578..4f7b087 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Allows the app to perform actions across different users on the device. Malicious apps may use this to violate the protection between users."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"full license to interact across users"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Allows all possible interactions across users."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"manage users"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Allows apps to manage users on the device, including query, creation and deletion."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"retrieve details of running apps"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Allows the app to retrieve detailed information about currently and recently running tasks. Malicious apps may discover private information about other apps."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"re-order running apps"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Done"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Media output"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Built-in Screen"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index b589afb..9108337 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que la aplicación lleve a cabo acciones entre los diferentes usuarios del dispositivo. Las aplicaciones maliciosas pueden utilizar este permiso para infringir la protección entre usuarios."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"Licencia completa para interactuar con los usuarios"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas las interacciones posibles con los usuarios."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Administrar usuarios"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite a las aplicaciones administrar a los usuarios del dispositivo, incluidas la creación y la eliminación de consultas."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar información sobre las aplicaciones en ejecución"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que la aplicación recupere información detallada sobre tareas en ejecución y recientemente ejecutadas. Las aplicaciones malintencionadas pueden hallar información privada sobre otras aplicaciones."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reorganizar aplicaciones en ejecución"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Listo"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Salida multimedia"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ec7bbb2..c998ff6 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que la aplicación lleve a cabo acciones entre los diferentes usuarios del dispositivo. Las aplicaciones maliciosas pueden utilizar este permiso para infringir la protección entre usuarios."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licencia completa para interactuar con los usuarios"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite que la aplicación interactúe con los usuarios."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"administrar usuarios"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite a las aplicaciones administrar los usuarios del dispositivo, así como buscarlos, crearlos y eliminarlos."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar información de aplicaciones en ejecución"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que la aplicación recupere información sobre tareas que se están ejecutando en este momento o que se han ejecutado recientemente. Las aplicaciones malintencionadas pueden usar este servicio para acceder a información privada sobre otras aplicaciones."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reorganizar aplicaciones en ejecución"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fin"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Salida multimedia"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Pantalla integrada"</string>
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 957e941..872f485 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Lubab rakendusel teha toiminguid seadme erinevatel kasutajakontodel. Pahatahtlikud rakendused võivad kasutada seda kasutajatevahelise kaitse rikkumiseks."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"täielik litsents teha toiminguid erinevatel kasutajakontodel"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Lubab kõiki võimalikke toiminguid erinevatel kasutajakontodel."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"kasutajate haldamine"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Võimaldab rakendustel hallata seadme kasutajaid, sealhulgas päringuid, loomist ja kustutamist."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"töötavate rakenduste üksikasjade toomine"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Võimaldab rakendusel tuua üksikasjalikku teavet praegu töötavate ja hiljuti käitatud ülesannete kohta. Pahatahtlikud rakendused võivad tuvastada privaatset teavet muude rakenduste kohta."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"käitatud rakenduste ümberjärjestamine"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-heli"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Meediaväljund"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 6f99078..ecdebe8 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"به برنامه اجازه می‌دهد اقداماتی در بین کاربران مختلف در دستگاه انجام دهد. ممکن است برنامه‌های مخرب از این قابلیت برای نقض حفاظت موجود در بین کاربران استفاده کنند."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"مجوز کامل برای ارتباط بین کاربران"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"اجازه می‌دهد همه ارتباطات ممکن بین کاربران انجام شود."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"مدیریت کاربران"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"به برنامه‌ها اجازه می‌دهد مدیریت کاربران، از قبیل پرسش، ایجاد و حذف کاربران، را در دستگاه انجام دهند."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"بازیابی جزئیات برنامه‌های در حال اجرا"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"به برنامه اجازه می‎دهد تا اطلاعات مفصلی مربوط به کارهایی که در حال حاضر و اخیراً اجرا می‎شوند را بازیابی کند. برنامه‎های مخرب می‎توانند اطلاعات شخصی مربوط به برنامه‎های دیگر را پیدا کنند."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"تنظیم مجدد ترتیب برنامه‎های در حال اجرا"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"بلوتوث‌های صوتی"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"انجام شد"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"خروجی رسانه"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e06dfcc..f6ab9f8 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Antaa sovelluksen suorittaa käyttäjien välisiä toimintoja laitteessa. Haitalliset sovellukset voivat vahingoittaa käyttäjien välistä suojausta."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lupa suorittaa käyttäjien välisiä toimintoja"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Sallii kaikki käyttäjien väliset toiminnot."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"hallinnoi käyttäjiä"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Antaa sovelluksien hallinnoida laitteen käyttäjiä esim. hakemalla, luomalla tai poistamalla käyttäjiä."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hae tiedot suoritettavista sovelluksista"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Antaa sovellukselle oikeuden noutaa käynnissä oleviin ja käynnissä olleisiin tehtäviin liittyviä tietoja. Haitalliset sovellukset saattavat saada näin muihin sovelluksiin liittyviä yksityisiä tietoja."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"käynnissä olevien sovellusten järjesteleminen"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ääni"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Median äänentoisto"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Sisäänrakennettu näyttö"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e98000a..c35fe8d 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permet à l\'application d\'effectuer des actions entre les différents utilisateurs de l\'appareil. Les applications malveillantes peuvent utiliser cette autorisation pour passer outre la protection entre les utilisateurs."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"autorisation totale d\'interagir entre les utilisateurs"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permet toutes les interactions possibles entre les utilisateurs."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Gérer les utilisateurs"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permet aux applications de gérer les utilisateurs de l\'appareil, y compris la recherche, la création et la suppression d\'utilisateurs."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"récupérer les détails des applications en cours d\'exécution"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permet à l\'application de récupérer des informations détaillées sur les tâches en cours d\'exécution ou récemment exécutées. Des applications malveillantes peuvent utiliser cette fonctionnalité pour obtenir des informations confidentielles relatives à d\'autres applications."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"réorganiser les applications en cours d\'exécution"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"OK"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Sortie multimédia"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index cf8fa01..6ea8f7b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"एप्लिकेशन को उपकरण पर भिन्न उपयोगकर्ताओं के बीच कार्य निष्पादित करने देता है. दुर्भावनापूर्ण एप्लिकेशन उपयोगकर्ताओं के बीच सुरक्षा का उल्लंघन करने के लिए इसका उपयोग कर सकते हैं."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"उपयोगकर्ताओं के बीच सहभागिता करने के लिए पूर्ण लाइसेंस"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"उपयोगकर्ताओं के बीच सभी संभव सहभागिता करने देता है."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"उपयोगकर्ता प्रबंधित करें"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"एप्लिकेशन को उपकरण पर क्वेरी, निर्माण और हटाने सहित उपयोगकर्ताओं को प्रबंधित करने की सुविधा देता है."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"चल रहे एप्‍लिकेशन के विवरण प्राप्त करें"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"एप्लिकेशन को वर्तमान में और हाल ही में चल रहे कार्यों की जानकारी प्राप्त करने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य एप्लिकेशन के बारे में निजी जानकारी खोज सकते हैं."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"चल रहे एप्‍लिकेशन पुन: क्रमित करें"</string>
@@ -722,7 +724,7 @@
     <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"आपका सिम कार्ड स्‍थायी रूप से अक्षम कर दिया गया है."\n" दूसरे SIM कार्ड के लिए अपने वायरलेस सेवा प्रदाता से संपर्क करें."</string>
     <string name="lockscreen_transport_prev_description" msgid="201594905152746886">"पिछला ट्रैक बटन"</string>
     <string name="lockscreen_transport_next_description" msgid="6089297650481292363">"अगला ट्रैक बटन"</string>
-    <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"रोकें बटन"</string>
+    <string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"पॉज़ करें बटन"</string>
     <string name="lockscreen_transport_play_description" msgid="5888422938351019426">"चलाएं बटन"</string>
     <string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"रोकें बटन"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"केवल आपातकालीन कॉल"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ऑडियो"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"पूर्ण"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"मीडिया आउटपुट"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 2029530..26bc6ec 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Omogućuje aplikaciji izvršavanje radnji među korisnicima na uređaju. Zlonamjerne aplikacije mogu to iskoristiti za narušavanje zaštite među korisnicima."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"dozvola za potpunu interakciju među korisnicima"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Omogućuje sve moguće interakcije među korisnicima."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"upravljanje korisnicima"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Omogućuje aplikacijama upravljanje korisnicima na uređaju, uključujući upit, izradu i brisanje."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"dohvaćanje pojedinosti o pokrenutim aplikacijama"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Aplikaciji omogućuje dohvaćanje detaljnih informacija o trenutačno i nedavno pokrenutim zadacima. Zlonamjerne aplikacije mogu otkriti privatne informacije o drugim aplikacijama."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"promjena redoslijeda pokrenutih aplikacija"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth zvuk"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gotovo"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Medijski izlaz"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 421c5be..42e7888 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Lehetővé teszi az alkalmazás számára, hogy több felhasználó között végezzen különféle műveleteket az eszközön. A rosszindulatú alkalmazások arra használhatják ezt, hogy megsértsék a felhasználók biztonságát."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"teljes licenc a felhasználók közötti interakcióhoz"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Lehetővé teszi az összes lehetséges interakciót a felhasználók között."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Felhasználók kezelése"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Lehetővé teszi az alkalmazások számára a készüléken beállított felhasználók kezelését, beleértve a lekérdezéseket, a létrehozásokat és törléseket."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"futó alkalmazások részleteinek lekérése"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Lehetővé teszi az alkalmazás számára a jelenleg és a nemrég futó feladatok részletes adatainak lekérését. A rosszindulatú alkalmazások más alkalmazásokkal kapcsolatos privát adatokhoz férhetnek hozzá."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"futó alkalmazások átrendezése"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth hang"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Kész"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Médiakimenet"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index ef759e0..34e6a96 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Mengizinkan aplikasi melakukan tindakan antar-pengguna yang berbeda pada perangkat. Aplikasi berbahaya dapat menggunakan ini untuk mengganggu perlindungan antar-pengguna."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lisensi penuh untuk berinteraksi antar-pengguna"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Mengizinkan semua interaksi yang mungkin antar-pengguna."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"kelola pengguna"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Memungkinkan aplikasi mengelola pengguna pada perangkat, termasuk kueri, pembuatan, dan penghapusan."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"mengambil detail aplikasi yang sedang berjalan"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Izinkan aplikasi mengambil informasi mendetail tentang tugas yang saat ini dan baru-baru ini dijalankan. Aplikasi berbahaya dapat menemukan informasi pribadi tentang aplikasi lain."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"menyusun ulang apl yang berjalan"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Selesai"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Keluaran media"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Layar Ada Di Dalamnya"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 5f64c20..a693dc8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Consente all\'applicazione di compiere azioni per diversi utenti sul dispositivo. Le applicazioni dannose potrebbero farne uso per violare la protezione tra utenti."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licenza completa per l\'interazione tra utenti"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Consente tutte le interazioni possibili tra gli utenti."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Gestione utenti"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Consente alle applicazioni di gestire gli utenti sul dispositivo, nonché query, creazione ed eliminazione."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recupero dettagli applicazioni in esecuzione"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Consente all\'applicazione di recuperare informazioni dettagliate sulle attività attualmente e recentemente in esecuzione. Le applicazioni dannose potrebbero scoprire informazioni riservate su altre applicazioni."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"riordinamento applicazioni in esecuzione"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fine"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Uscita media"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Schermo incorporato"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5432f26..a318907 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"מאפשר ליישום לבצע פעולות בין משתמשים שונים במכשיר. יישומים זדוניים עשויים להשתמש ביכולת זו כדי לפרוץ את ההגנה בין משתמשים."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"רישיון מלא לבצע אינטראקציה בין משתמשים"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"מאפשר את כל האינטראקציות האפשריות בין משתמשים."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"נהל משתמשים"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"מאפשר ליישומים לנהל משתמשים במכשיר, כולל שאילתה, יצירה ומחיקה."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"אחזור פרטי יישומים פועלים"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"מאפשר ליישום לאחזר מידע מפורט על המשימות הנוכחיות הפועלות ועל משימות שפעלו לאחרונה. יישומים זדוניים עלולים לגלות מידע אישי על יישומים אחרים."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"סידור מחדש של יישומים פעילים"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"אודיו Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"סיום"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"פלט מדיה"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"מסך מובנה"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index f8ab2bf..dc0c139 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"端末上の各ユーザーに対して操作を実行することをアプリに許可します。この許可を悪意のあるアプリに利用されると、ユーザー間の保護が侵害される恐れがあります。"</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ユーザー間で交流するための完全ライセンス"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"ユーザー間の交流をすべて許可します。"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"ユーザーの管理"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"ユーザーの問い合わせ、作成、削除を含め、端末上のユーザーを管理することをアプリに許可します。"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"実行中のアプリの詳細の取得"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"現在実行中のタスクまたは最近実行したタスクに関する情報の取得をアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリに関する非公開情報が読み取られる恐れがあります。"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"実行中のアプリの順序変更"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth音声"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完了"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"メディア出力"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index ec301a4..f6ae2af 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"앱이 기기에서 다양한 사용자에 대한 작업을 수행할 수 있도록 허용합니다. 이 경우 악성 앱이 사용자 간의 보호를 위반할 수 있습니다."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"여러 사용자와의 상호작용을 위한 정식 라이센스"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"여러 사용자와의 가능한 모든 상호작용을 허용합니다."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"사용자 관리"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"앱이 기기에서 검색, 생성 및 삭제를 포함한 사용자 관리를 할 수 있도록 허용합니다."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"실행 중인 앱 세부정보 검색"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 상세한 정보를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 다른 앱에 대한 개인 정보를 검색할 수 있습니다."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"실행 중인 앱 순서 재지정"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"블루투스 오디오"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"완료"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"미디어 출력"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7f44e81..7692620 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Leidžiama programai atlikti veiksmus skirtingų įrenginio naudotojų profiliuose. Kenkėjiškos programos gali pasinaudoti šiuo leidimu, kad pažeistų naudotojų saugumą."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"visa licencija, leidžianti sąveikauti su naudotojais"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Leidžiama bet kokia sąveika tarp naudotojų."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"tvarkyti naudotojus"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Leidžia tvarkyti įrenginio naudotojų duomenis, įskaitant užklausų teikimą, duomenų kūrimą ir ištrynimą."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"nuskaityti veikiančių programų išsamią informaciją"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Leidžiama programai nuskaityti išsamią informaciją apie šiuo ir pastaruoju metu vykdomas užduotis. Kenkėjiškos programos gali surasti privačios informacijos apie kitas programas."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"pertvarkyti vykdomas programas"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"„Bluetooth“ garsas"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Atlikta"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Medijos išvestis"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1d46ccb..d63c45b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ļauj lietotnei veikt darbības vairāku ierīces lietotāju kontos. Ļaunprātīgas lietotnes var izmantot šo atļauju, lai apdraudētu lietotāju kontu drošību."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"pilna licence ar atļauju darboties visos lietotāju kontos"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ļauj veikt jebkādas darbības visos lietotāju kontos."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Lietotāju pārvaldība"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ļauj lietotnēm pārvaldīt ierīces lietotājus, tostarp izveidot un dzēst lietotājus vai veidot vaicājumus."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Informācijas izguve par izmantotajām lietotnēm"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ļauj lietotnei izgūt informāciju par šobrīd un nesen veiktajiem uzdevumiem. Ļaunprātīgas lietotnes var atklāt privātu informāciju par citām lietotnēm."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"pārkārtot izmantotās lietotnes"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gatavs"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Multivides izeja"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5bbebc5..a22ff51 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Membenarkan apl melakukan tindakan merentasi pengguna berbeza pada peranti. Apl hasad boleh menggunakan ini untuk melanggar perlindungan antara pengguna."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"lesen penuh untuk berinteraksi sesama pengguna"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Membenarkan semua interaksi yang mungkin sesama pengguna."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"urus pengguna"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Membenarkan apl mengurus pengguna pada peranti ini, termasuk pertanyaan, pembuatan dan pemadaman."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"dapatkan butiran apl yang berjalan"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Membenarkan apl untuk mendapatkan maklumat terperinci tentang tugasan yang sedang dan baru berjalan. Apl hasad boleh mendapat maklumat peribadi tentang apl lain."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"susun semula tertib apl yang dijalankan"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Selesai"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Output media"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 68f8918..3a4212b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillater at appen utfører handlinger på tvers av ulike brukere på enheten. Skadelige apper kan utnytte dette til å bryte beskyttelsen mellom brukere."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"full lisens til å samhandle på tvers av brukere"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillater alle mulige samhandlinger på tvers av brukere."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Administrere brukere"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Lar apper administrere brukere på enheten, herunder forespørsler, oppretting og sletting."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hente informasjon om apper som kjører"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillater at appen henter ut informasjon om oppgaver som kjører eller nylig har kjørt. Skadelige apper kan bruke dette til å oppdage privat informasjon om andre apper."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"Endre rekkefølge på apper som kjører"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fullført"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieutgang"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Innebygd skjerm"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 985da7e9..89e52a9 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Hiermee kan de app acties uitvoeren voor verschillende gebruikers van het apparaat. Schadelijke apps kunnen dit gebruiken om de beveiliging tussen gebruikers te schenden."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"volledige toestemming voor interactie tussen gebruikers"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Hiermee is alle mogelijke interactie tussen gebruikers toegestaan."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gebruikers beheren"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Toestaan dat apps gebruikers op het apparaat beheren, inclusief het opvragen van gegevens en het maken en verwijderen van gebruikers."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"details van actieve apps ophalen"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Hiermee kan de app gedetailleerde informatie over huidige en recent uitgevoerde taken ophalen. Schadelijke apps kunnen op deze manier mogelijk privé-informatie over andere apps achterhalen."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"actieve apps opnieuw rangschikken"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gereed"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Media-uitvoer"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Ingebouwd scherm"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 19f317d..e16d308 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umożliwia aplikacji wykonywanie działań dotyczących różnych użytkowników urządzenia. Złośliwe aplikacje mogą to wykorzystać do złamania zabezpieczeń na kontach użytkowników."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"pełna licencja na interakcje między użytkownikami"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Zezwala na wszystkie możliwe interakcje między użytkownikami."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"zarządzanie użytkownikami"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Pozwala aplikacjom na zarządzanie użytkownikami na urządzeniu, w tym na ich sprawdzanie, tworzenie i usuwanie."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"Pobieraj informacje o uruchomionych aplikacjach"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Zezwala aplikacji na pobieranie informacji o obecnie i ostatnio uruchomionych zadaniach. Złośliwe aplikacje mogą uzyskać dostęp do prywatnych informacji na temat innych aplikacji."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"zmienianie kolejności uruchomionych aplikacji"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Dźwięk Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gotowe"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Wyjście multimediów"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 788d1a2..996be49 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que a aplicação execute ações com diferentes utilizadores no dispositivo. Aplicações maliciosas poderão utilizar esta opção para violar a proteção entre utilizadores."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licença completa para interagir entre utilizadores"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas as interações possíveis entre utilizadores."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gerir utilizadores"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite às aplicações a gestão de utilizadores no dispositivo, incluindo a criação e eliminação de consultas."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"obter detalhes das aplicações em execução"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite à aplicação obter informações detalhadas sobre tarefas atualmente em execução e recentemente executadas. As aplicações maliciosas poderão descobrir informações privadas de outras aplicações."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar as aplicações em execução"</string>
@@ -1132,7 +1134,7 @@
     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"O armazenamento USB foi removido. Insira um novo suporte de dados."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Cartão SD removido. Insira um novo cartão."</string>
     <string name="activity_list_empty" msgid="1675388330786841066">"Não foi encontrada nenhuma atividade correspondente."</string>
-    <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar estatísticas de utilização de componentes"</string>
+    <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"atualizar estatísticas de utilização de componentes"</string>
     <string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"Permite que a aplicação modifique as estatísticas de utilização de componentes recolhidas. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_copyProtectedData" msgid="4341036311211406692">"copiar conteúdo"</string>
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"Permite à aplicação invocar o serviço de contentor predefinido para copiar conteúdo. Não se destina a ser utilizado por aplicações normais."</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Concluído"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Saída de som multimédia"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 9bdfcd8..7d7672f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite que o aplicativo execute ações entre os diversos usuários do aparelho. Aplicativos mal-intencionados podem usar isto para violar a proteção entre os usuários."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"permissão total para interagir entre os usuários"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite todas as interações possíveis entre os usuários."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gerenciar usuários"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite que os aplicativos gerenciem os usuários do dispositivo, incluindo a consulta, a criação e a exclusão de usuários."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"recuperar detalhes dos aplicativos em execução"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite que o aplicativo recupere informações detalhadas sobre tarefas executadas atual e recentemente. Aplicativos maliciosos podem descobrir informações privadas sobre outros aplicativos."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar os aplicativos em execução"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Concluído"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Saída de mídia"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 097d6de..a093bfb 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -303,6 +303,10 @@
     <skip />
     <!-- no translation found for permdesc_interactAcrossUsersFull (376841368395502366) -->
     <skip />
+    <!-- no translation found for permlab_manageUsers (1676150911672282428) -->
+    <skip />
+    <!-- no translation found for permdesc_manageUsers (8409306667645355638) -->
+    <skip />
     <!-- no translation found for permlab_getDetailedTasks (6229468674753529501) -->
     <skip />
     <!-- no translation found for permdesc_getDetailedTasks (153824741440717599) -->
@@ -2066,4 +2070,6 @@
     <skip />
     <!-- no translation found for media_route_button_content_description (5758553567065145276) -->
     <skip />
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 7284dd7..6300a1f4 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Permite aplicaţiei să efectueze acţiuni pentru diferiţi utilizatori pe dispozitiv. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a încălca protecţia între utilizatori."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"licenţă completă pentru interacţiune între utilizatori"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Permite toate interacţiunile posibile între utilizatori."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"gestionează utilizatorii"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Permite aplicaţiilor să gestioneze utilizatorii de pe dispozitiv, inclusiv interogarea, crearea şi ştergerea acestora."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"preia detalii despre aplicaţiile care rulează"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Permite aplicaţiei să preia informaţii detaliate despre activităţile rulate curent şi recent. Aplicaţiile rău intenţionate pot să descopere informaţii private despre alte aplicaţii."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordonare aplicaţii care rulează"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Terminat"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Rezultate media"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index c32f93a..004b2b6 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Приложение сможет выполнять действия во всех аккаунтах на этом устройстве. При этом защита от вредоносных приложений может быть недостаточной."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"разрешить полное взаимодействие со всеми аккаунтами"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Приложение сможет выполнять любые действия во всех аккаунтах на этом устройстве."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"Управлять аккаунтами"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Приложения смогут управлять аккаунтами на этом устройстве (выполнять поиск, создавать и удалять их)"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"получение сведений о работающих приложениях"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Приложение сможет получать подробные сведения о недавно запущенных и выполняемых задачах. При этом конфиденциальная информация о других приложениях не будет защищена от вредоносных программ."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"Упорядочивание запущенных приложений"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Воспроизведение звука через Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Перенаправлять поток мультимедиа"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 3464faa..15c359c 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Umožňuje aplikácii vykonávať akcie naprieč rôznymi používateľmi zariadenia. Škodlivé aplikácie môžu toto povolenie zneužiť na obídenie ochrany medzi používateľmi."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"plná licencia na interakcie naprieč používateľmi"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Umožňuje všetky možné interakcie naprieč používateľmi."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"správa používateľov"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Umožňuje aplikáciám spravovať používateľov v zariadení, vrátane vyhľadávania dopytov, vytvorenia a odstránenia."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"načítať podrobnosti o spustených aplikáciách"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Umožňuje aplikácii načítať podrobné informácie o aktuálnych a nedávno spustených úlohách. Škodlivé aplikácie môžu odhaliť súkromné informácie o iných aplikáciách."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"zmeniť poradie spustených aplikácií"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Hotovo"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Výstup médií"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 35246b1..1ede6b7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Aplikaciji omogoča izvajanje dejanj za različne uporabnike v napravi. Zlonamerne aplikacije lahko to uporabijo za kršitev zaščite med uporabniki."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"polna licenca za interakcijo z uporabniki"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Dovoli vso mogočo interakcijo z uporabniki"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"upravljanje uporabnikov"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Aplikacijam omogoča upravljanje uporabnikov v napravi, vključno z iskanjem, ustvarjanjem in brisanjem."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"prejemanje podrobnosti o aplikacijah, ki se izvajajo"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Aplikaciji omogoča, da dobi podatke o trenutnih in nedavno izvajajočih se opravilih. Zlonamerne aplikacije lahko odkrijejo zasebne podatke o drugih aplikacijah."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"preurejanje programov, ki se izvajajo"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Zvok prek Bluetootha"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Končano"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Izhod predstavnosti"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Vgrajen zaslon"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index d5c0561..e4cf347 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дозвољава апликацији да обавља радње између различитих корисника на уређају. Злонамерне апликације могу да користе ово да би угрозиле заштиту између корисника."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"пуна лиценца за интеракцију између корисника"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дозвољава све могуће интеракције између корисника."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"управљање корисницима"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дозвољава апликацијама да управљају корисницима на уређају, укључујући постављање упита, прављење и брисање."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"преузимање детаља о покренутим апликацијама"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дозвољава апликацији да преузима детаљне информације о актуелним и недавно покренутим задацима. Злонамерне апликације могу да открију приватне информације о другим апликацијама."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"промена редоследа покренутих апликација"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth аудио"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Излаз медија"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 89c0796d..493a0bb 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Tillåter att appen utför åtgärder mellan användare på enheten. Skadliga appar kan använda detta som ett sätt att kringgå skyddet mellan användare."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"fullständig behörighet att interagera mellan användare"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Tillåter all slags interaktion mellan användare."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"hantera användare"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Tillåter att appen hanterar användare på enheten, inklusive att söka efter, skapa och radera användarinformation."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"hämta information om aktiva appar"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Tillåter att appen hämtar detaljerad information om uppgifter som körs och har körts. Skadliga appar kan upptäcka personliga uppgifter om andra appar."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"byt ordning på appar som körs"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ljud"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Klar"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieuppspelning"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Inbyggd skärm"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 3fd7af05..759000d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Inaruhusu programu kutenda vitendo kwa watumiaji tofauti kwenye kifaa. Programu hasidi huenda zikatumia hii ili kukiuka ulinzi kati ya watumiaji."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"leseni kamili ili kutagusana na watumiaji"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Inaruhusu miingialiano yote inayowezekana kwa watumiaji."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"dhibiti watumiaji"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Inaruhusu programu kudhibiti watumiaji kwenye kifaa, pamoja na hoji, uundaji na ufutaji."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"epua maelezo ya programu zinazoendeshwa"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Huruhusu programu kuepua maelezo tondoti kuhusu kazi za sasa na zinazoendelea hivi karibuni. Programu hasidi huenda zikagundua maelezo ya kibinafsi kuhusu programu zingine."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"Agiza tena programu za kuendeshwa"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Sauti ya Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Kwisha"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Towe la midia"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Skrini Iliyojengewa ndani"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 61e25b2..c25e6db 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"อนุญาตให้แอปพลิเคชันทำงานได้กับผู้ใช้หลายรายบนอุปกรณ์นี้ แอปพลิเคชันที่เป็นอันตรายอาจใช้การทำงานนี้ในการบุกรุกการป้องกันระหว่างผู้ใช้"</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ใบอนุญาตฉบับเต็มสำหรับการโต้ตอบระหว่างผู้ใช้"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"อนุญาตให้ทำการโต้ตอบทุกชนิดที่เป็นไปได้กับผู้ใช้ต่างๆ"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"จัดการผู้ใช้"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"อนุญาตให้แอปพลิเคชันจัดการผู้ใช้บนอุปกรณ์ รวมทั้งการถามคำถาม การสร้าง และการลบ"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"ดึงรายละเอียดของแอปที่ทำงานอยู่"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"อนุญาตให้แอปพลิเคชันดึงข้อมูลเกี่ยวกับงานที่กำลังเรียกใช้อยู่ในปัจจุบันและงานล่าสุด แอปพลิเคชันที่เป็นอันตรายอาจค้นพบข้อมูลเฉพาะตัวเกี่ยวกับแอปพลิเคชันอื่นๆ"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"จัดลำดับแอปพลิเคชันที่ทำงานอยู่ใหม่"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"เสียงบลูทูธ"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"เสร็จสิ้น"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"เอาต์พุตสื่อ"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index adf7ef2..ab4ff29 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Binibigyang-daan ang app upang magsagawa ng mga pagkilos sa kabuuan ng iba\'t ibang mga user sa device. Maaari itong gamitin ng nakakahamak na apps upang lumabag sa proteksyon sa pagitan ng mga user."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ganap na lisensya upang makipag-ugnayan sa kabuuan ng mga user"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Pinapayagan ang lahat ng posibleng pakikipag-ugnayan sa kabuuan ng mga user."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"pamahalaan ang mga user"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Binibigyang-daan ang apps na mamahala ng mga user sa device, kabilang ang query, paglikha at pagtanggal."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"bawiin ang mga detalye ng gumaganang apps"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Binibigyang-daan ang app na bawiin ang detalyadong impormasyon tungkol sa mga kasalukuyan at kamakailang gumaganang gawain. Maaaring makatuklas ang nakakahamak na apps ng pribadong impormasyon tungkol sa iba pang apps."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"muling isaayos ang tumatakbong apps"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio sa Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Tapos na"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Output ng media"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e15402a..95637dc 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Uygulamaya cihazdaki farklı kullanıcılar arasında işlem gerçekleştirme izni verir. Kötü amaçlı uygulamalar bu izinle kullanıcılar arasındaki korumayı ihlal edebilir."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"kullanıcılar arasında etkileşim kurmak için tam izin"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Kullanıcılar arasında tüm etkileşime izin verir."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"kullanıcıları yönet"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Uygulamalara, sorgulama, oluşturma ve silme işlemleri de dahil olmak üzere cihazdaki kullanıcıları yönetme izni verir."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"çalışan uygulamaların ayrıntılarını al"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Uygulamaya, şu anda çalışmakta olan ve son çalışan işlemler hakkında ayrıntılı bilgi alma izni verir. Kötü amaçlı uygulamalar diğer uygulamalar hakkında gizli bilgileri ele geçirebilir."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"çalışan uygulamaları yeniden sırala"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ses"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Tamamlandı"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Medya çıkışı"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d37cbd8..a8633e8 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Дозволяє програмі виконувати дії щодо різних користувачів на пристрої. Шкідливі програми можуть використовувати це для порушення захисту окремих користувачів."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"повна ліцензія на взаємодію між користувачами"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Дозволяє всі можливі взаємодії щодо користувачів."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"керувати користувачами"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Дозволяє програмам керувати користувачами на пристрої, зокрема надсилати запити про користувачів, створювати й видаляти їх."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"отримувати дані про запущені програми"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Дозволяє програмі отримувати інформацію про поточні й останні запущені завдання. Шкідливі програми можуть виявляти особисту інформацію про інші програми."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"змінювати порядок запущених програм"</string>
@@ -1309,4 +1311,5 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Аудіо Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Вивід медіа-даних"</string>
+    <string name="display_manager_built_in_display" msgid="9042666544146043569">"Вбудований екран"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8ce6f4e..384a1ee 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Cho phép ứng dụng thực hiện hành động giữa những người dùng khác trên thiết bị. Ứng dụng độc hại có thể sử dụng quyền này để vi phạm khả năng bảo vệ giữa người dùng."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"cấp phép đầy đủ để tương tác giữa người dùng"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Cho phép tất cả các tương tác giữa người dùng."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"quản lý người dùng"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Cho phép ứng dụng quản lý người dùng trên thiết bị, bao gồm truy vấn, tạo và xóa."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"truy xuất chi tiết về các ứng dụng đang chạy"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Cho phép ứng dụng truy xuất thông tin chi tiết về các tác vụ đã và đang chạy gần đây. Ứng dụng độc hại có thể phát hiện thông tin riêng tư về các ứng dụng khác."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"sắp xếp lại những ứng dụng đang chạy"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Âm thanh Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Xong"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Đầu ra phương tiện"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c271baa..289dcf8 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"允许该应用在设备上跨多个用户执行操作。恶意应用可能会借此破坏用户之间的保护措施。"</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"完全允许在用户之间进行互动"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"允许在用户之间进行所有可能的互动。"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"管理用户"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"允许应用管理设备上的用户(包括查询、创建和删除用户)。"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"检索正在运行的应用的详细信息"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"允许该应用检索当前正在运行和近期运行的任务的详细信息。恶意应用可能会发现有关其他应用的私密信息。"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"对正在运行的应用重新排序"</string>
@@ -1068,13 +1070,13 @@
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff900000">"新增:"</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"由“<xliff:g id="APP_NAME">%1$s</xliff:g>”提供。"</string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"USB 大容量存储设备"</string>
-    <string name="usb_storage_title" msgid="5901459041398751495">"USB 已连接"</string>
+    <string name="usb_storage_title" msgid="5901459041398751495">"已连接 USB"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"您已通过 USB 连接至计算机。如果您要在计算机与 Android 设备的 USB 存储设备之间复制文件,请触摸下面的按钮。"</string>
     <string name="usb_storage_message" product="default" msgid="805351000446037811">"您已通过 USB 连接至计算机。如果您要在计算机和 Android 设备的 SD 卡之间复制文件,请触摸下面的按钮。"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"打开 USB 存储设备"</string>
     <string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"使用 USB 存储设备作为 USB 大容量存储设备时出现问题。"</string>
     <string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"使用 SD 卡作为 USB 大容量存储设备时出现问题。"</string>
-    <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已连接"</string>
+    <string name="usb_storage_notification_title" msgid="8175892554757216525">"已连接 USB"</string>
     <string name="usb_storage_notification_message" msgid="939822783828183763">"触摸可将文件复制到计算机或从计算机复制到存储设备。"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"触摸可关闭 USB 存储设备。"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"蓝牙音频"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"媒体输出线路"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 20a15d1..96ba8c1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"允許應用程式對裝置上的所有使用者執行各種動作。請注意,惡意應用程式可能利用此功能侵害使用者之間的保護機制。"</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"完整授權對所有使用者執行各種動作"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"允許對所有使用者執行各種可能的動作。"</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"管理使用者"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"允許應用程式管理裝置上的使用者,包括查詢、建立及刪除使用者。"</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"擷取執行中應用程式的詳細資訊"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"允許應用程式擷取目前及最近所執行任務的詳細資訊。請注意,惡意應用程式可能會找出其他應用程式的不公開資訊。"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"重新排序正在執行的應用程式"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"藍牙音訊"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"媒體輸出"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 8978e52..2a17f8f 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -224,6 +224,8 @@
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Ivumela uhlelo lokusebenza ukwenza izenzo kubasebenzisi bonke kudivayisi. Izinhlelo zokusebenza ezingalungile zingasebenzisa lokhu ukwephula ukuvikela phakathi kwabasebenzisi."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"ilayisensi egcwele yokuhlanganyela kubasebenzisi"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Ivumela konke ukuhlanganyela phakathi kwabasebenzisi."</string>
+    <string name="permlab_manageUsers" msgid="1676150911672282428">"phatha abasebenzisi"</string>
+    <string name="permdesc_manageUsers" msgid="8409306667645355638">"Ivumela izinhlelo zokusebenza ukuphatha abasebenzisi kudivayisi, kufaka phakathi umbuzo, ukudala nokususa."</string>
     <string name="permlab_getDetailedTasks" msgid="6229468674753529501">"thola kabusha imininingwane yezinhlelo zokusebenza ezisebenzayo"</string>
     <string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Ivumela uhlelo lokusebenza ukuthola kabusha ulwazi mayelana nezinto ezenzeka manje nezisanda kwenzeka. Izinhlelo zokusebenza ezingalungile zingathola imininingwane eyimfihlo mayelana nezinye izinhlelo zokusebenza."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"misa kabusha izinsiza ezisebenzayo"</string>
@@ -1309,4 +1311,6 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Umsindo we-Bluetooth"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Qedile"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Okukhiphayo kwemidiya"</string>
+    <!-- no translation found for display_manager_built_in_display (9042666544146043569) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 38a431f..0d190ee 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -479,6 +479,7 @@
   <java-symbol type="string" name="decline" />
   <java-symbol type="string" name="default_text_encoding" />
   <java-symbol type="string" name="description_target_unlock_tablet" />
+  <java-symbol type="string" name="display_manager_built_in_display" />
   <java-symbol type="string" name="double_tap_toast" />
   <java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" />
   <java-symbol type="string" name="elapsed_time_short_format_mm_ss" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 620a002..b7ad1e9 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3639,4 +3639,9 @@
     <!-- Content description of a MediaRouteButton for accessibility support -->
     <string name="media_route_button_content_description">Media output</string>
 
+    <!-- Display manager service -->
+
+    <!-- Name of the built-in display.  [CHAR LIMIT=50] -->
+    <string name="display_manager_built_in_display">Built-in Screen</string>
+
 </resources>
diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
index 8d53db9..aae55e8 100755
--- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
@@ -570,7 +570,7 @@
             PackageStatsObserver observer = new PackageStatsObserver();
             //wait on observer
             synchronized(observer) {
-                getPm().getPackageSizeInfo(packageName, observer);
+                getPm().getPackageSizeInfo(packageName, UserHandle.myUserId(), observer);
                 long waitTime = 0;
                 while((!observer.isDone()) || (waitTime > MAX_WAIT_TIME) ) {
                     observer.wait(WAIT_TIME_INCR);
diff --git a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
new file mode 100644
index 0000000..b814e2d
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 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.pm;
+
+import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
+import android.net.Uri;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+/**
+ * Tests the android.content.pm.VerificationParams class
+ *
+ * To test run:
+ * ./development/testrunner/runtest.py frameworks-core -c android.content.pm.VerificationParamsTest
+ */
+public class VerificationParamsTest extends AndroidTestCase {
+
+    private final static String VERIFICATION_URI_STRING = "http://verification.uri/path";
+    private final static String ORIGINATING_URI_STRING = "http://originating.uri/path";
+    private final static String REFERRER_STRING = "http://referrer.uri/path";
+    private final static byte[] DIGEST_BYTES = "fake digest".getBytes();
+
+    private final static Uri VERIFICATION_URI = Uri.parse(VERIFICATION_URI_STRING);
+    private final static Uri ORIGINATING_URI = Uri.parse(ORIGINATING_URI_STRING);
+    private final static Uri REFERRER = Uri.parse(REFERRER_STRING);
+
+    private final static ManifestDigest MANIFEST_DIGEST = new ManifestDigest(DIGEST_BYTES);
+
+    public void testParcel() throws Exception {
+        VerificationParams expected = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        Parcel parcel = Parcel.obtain();
+        expected.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        VerificationParams actual = VerificationParams.CREATOR.createFromParcel(parcel);
+
+        assertEquals(VERIFICATION_URI, actual.getVerificationURI());
+
+        assertEquals(ORIGINATING_URI, actual.getOriginatingURI());
+
+        assertEquals(REFERRER, actual.getReferrer());
+
+        assertEquals(MANIFEST_DIGEST, actual.getManifestDigest());
+    }
+
+    public void testEquals_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1, params2);
+    }
+
+    public void testEquals_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+            REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse("http://a.different.uri/"), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse("http://a.different.uri/"), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testHashCode_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1.hashCode(), params2.hashCode());
+    }
+
+    public void testHashCode_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(null, Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING), null,
+                new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+}
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 3d6c9d3..7bc172c 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -76,14 +76,6 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
 include $(BUILD_PREBUILT)
 
-include $(CLEAR_VARS)
-LOCAL_MODULE := fallback_fonts-ja.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
 droidsans_fallback_src := DroidSansFallbackFull.ttf
 extra_font_files := \
 	DroidSans.ttf \
@@ -91,8 +83,7 @@
 	DroidSansEthiopic-Regular.ttf \
 	DroidSansTamil-Regular.ttf \
 	DroidSansTamil-Bold.ttf \
-	MTLmr3m.ttf \
-	fallback_fonts-ja.xml
+	MTLmr3m.ttf
 endif  # SMALLER_FONT_FOOTPRINT
 
 ################################
diff --git a/data/fonts/fallback_fonts-ja.xml b/data/fonts/fallback_fonts-ja.xml
deleted file mode 100644
index 82e3a38..0000000
--- a/data/fonts/fallback_fonts-ja.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Fallback Fonts
-
-    This file specifies the fonts, and the priority order, that will be searched for any
-    glyphs not handled by the default fonts specified in /system/etc/system_fonts.xml.
-    Each entry consists of a family tag and a list of files (file names) which support that
-    family. The fonts for each family are listed in the order of the styles that they
-    handle (the order is: regular, bold, italic, and bold-italic). The order in which the
-    families are listed in this file represents the order in which these fallback fonts
-    will be searched for glyphs that are not supported by the default system fonts (which are
-    found in /system/etc/system_fonts.xml).
-
-    Note that there is not nameset for fallback fonts, unlike the fonts specified in
-    system_fonts.xml. The ability to support specific names in fallback fonts may be supported
-    in the future. For now, the lack of files entries here is an indicator to the system that
-    these are fallback fonts, instead of default named system fonts.
-
-    There is another optional file in /vendor/etc/fallback_fonts.xml. That file can be used to
-    provide references to other font families that should be used in addition to the default
-    fallback fonts. That file can also specify the order in which the fallback fonts should be
-    searched, to ensure that a vendor-provided font will be used before another fallback font
-    which happens to handle the same glyph.
-
-    Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
-    their ordering in the fallback or vendor files gives priority to the first in the list.
-    Locale-specific ordering can be configured by adding language and region codes to the end
-    of the filename (e.g. /system/etc/fallback_fonts-ja.xml). When no region code is used,
-    as with this example, all regions are matched. Use separate files for each supported locale.
-    The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
-    file. All fallback files must contain the same complete set of fonts; only their ordering
-    can differ.
--->
-<familyset>
-    <family>
-        <fileset>
-            <file variant="elegant">DroidNaskh-Regular.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file variant="compact">DroidNaskh-Regular-SystemUI.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansEthiopic-Regular.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansHebrew-Regular.ttf</file>
-            <file>DroidSansHebrew-Bold.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansThai.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansArmenian.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansGeorgian.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansDevanagari-Regular.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansTamil-Regular.ttf</file>
-            <file>DroidSansTamil-Bold.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>AnjaliNewLipi-light.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>Lohit-Bengali.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>Lohit-Kannada.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>AndroidEmoji.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>MTLmr3m.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
-            <file>DroidSansFallback.ttf</file>
-        </fileset>
-    </family>
-    <!--
-        Fonts below this point have problematic glyphs and should not be moved
-        higher in the fallback list until those glyphs have been fixed.
-    -->
-    <family>
-        <fileset>
-            <file>Lohit-Telugu.ttf</file> <!-- masks U+FFBC-10007 -->
-        </fileset>
-    </family>
-</familyset>
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 758adb5..2c9a0c8 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -24,12 +24,9 @@
 
     Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
     their ordering in the fallback or vendor files gives priority to the first in the list.
-    Locale-specific ordering can be configured by adding language and region codes to the end
-    of the filename (e.g. /system/etc/fallback_fonts-ja.xml). When no region code is used,
-    as with this example, all regions are matched. Use separate files for each supported locale.
-    The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
-    file. All fallback files must contain the same complete set of fonts; only their ordering
-    can differ.
+    Language-specific ordering can be configured by adding a BCP 47-style "lang" attribute to
+    a "file" element; fonts matching the language of text being drawn will be prioritised over
+    all others.
 -->
 <familyset>
     <family>
@@ -106,7 +103,7 @@
     </family>
     <family>
         <fileset>
-            <file>MTLmr3m.ttf</file>
+            <file lang="ja">MTLmr3m.ttf</file>
         </fileset>
     </family>
     <!--
diff --git a/data/fonts/vendor_fonts.xml b/data/fonts/vendor_fonts.xml
index 5850f94..8690ee1 100644
--- a/data/fonts/vendor_fonts.xml
+++ b/data/fonts/vendor_fonts.xml
@@ -7,8 +7,7 @@
     that in your makefile, this directory should be referenced as $(TARGET_COPY_OUT_VENDOR)/etc/:
 
         PRODUCT_COPY_FILES += \
-            frameworks/base/data/fonts/vendor_fonts.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts.xml \
-            frameworks/base/data/fonts/vendor_fonts-ja.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts-ja.xml
+            frameworks/base/data/fonts/vendor_fonts.xml:$(TARGET_COPY_OUT_VENDOR)/etc/fallback_fonts.xml
 
     For example, vendors might want to build configurations for locales that are
     better served by fonts which either handle glyphs not supported in the default fonts or which
@@ -32,32 +31,9 @@
 
     Han languages (Chinese, Japanese, and Korean) share a common range of unicode characters;
     their ordering in the fallback or vendor files gives priority to the first in the list.
-    Locale-specific ordering can be configured by adding language and region codes to the end
-    of the filename (e.g. /vendor/etc/fallback_fonts-ja.xml). When no region code is used,
-    as with this example, all regions are matched. Use separate files for each supported locale.
-    The standard fallback file (fallback_fonts.xml) is used when a locale does not have its own
-    file. All fallback files must contain the same complete set of fonts; only their ordering
-    can differ. For example, on a device supporting Japanese, but with English as the default,
-    /vendor/etc/fallback_fonts.xml might contain:
-
-        <familyset>
-            <family>
-                <fileset>
-                    <file>DroidSansJapanese.ttf</file>
-                </fileset>
-            </family>
-        </familyset>
-
-    placing the Japanese font at the end of the fallback sequence for English, with a corresponding
-    /system/vendor/etc/fallback_fonts-ja.xml, placing it at the front of the list.
-
-        <familyset>
-            <family order="0">
-                <fileset>
-                    <file>DroidSansJapanese.ttf</file>
-                </fileset>
-            </family>
-        </familyset>
+    Language-specific ordering can be configured by adding a BCP 47-style "lang" attribute to
+    a "file" element; fonts matching the language of text being drawn will be prioritised over
+    all others.
 
     The sample configuration below is an example of how one might provide two families of fonts
     that get inserted at the first and second (0  and 1) position in the overall fallback fonts.
@@ -82,4 +58,4 @@
         </fileset>
     </family>
 </familyset>
--->
\ No newline at end of file
+--->
diff --git a/docs/html/intl/ja/index.jd b/docs/html/intl/ja/index.jd
deleted file mode 100644
index ac36f90..0000000
--- a/docs/html/intl/ja/index.jd
+++ /dev/null
@@ -1,159 +0,0 @@
-home=true
-@jd:body
-
-
-	<div id="mainBodyFixed">
-              <div id="mainBodyLeft">			
-                    <div id="homeMiddle">
-                        <div id="topAnnouncement">
-                            <div id="homeTitle">
-                                <h2>デベロッパーへのお知らせ</h2>
-                            </div><!-- end homeTitle -->
-                            <div id="announcement-block">
-                            <!-- total max width is 520px -->
-                                <img src="/assets/images/home/android_adc.png" alt="Android Developer Challenge 2" width="232px" />
-                                <div id="announcement" style="width:275px">
-                                  <p>第2Android Developer Challengeが、遂に登場しました!このアプリケーション開発コンテストでは、Androidのユーザなら誰でも簡単に参加でき、一等の賞金は$250,000 です。登録の締切日は8月31日になります。</p>
-                                  <p><a href="http://code.google.com/android/adc/">Android  Developer Challengeについて詳しくはこちら &raquo;</a></p>
-                                </div> <!-- end annoucement -->
-                            </div> <!-- end annoucement-block -->  
-                        </div><!-- end topAnnouncement -->
-                        <div id="carouselMain" style="height:210px"> <!-- this height can be adjusted based on the content height -->
-                        </div>
-                            <div class="clearer"></div>
-                        <div id="carouselWheel">
-                            <div class="app-list-container" align="center"> 
-                                <a href="javascript:{}" id="arrow-left" onclick="" class="arrow-left-off"></a>
-                                <div id="list-clip">
-                                    <div style="left: 0px;" id="app-list">
-                                      <!-- populated by buildCarousel() -->
-                                    </div>
-                                </div><!-- end list-clip -->
-                                <a href="javascript:{ page_right(); }" id="arrow-right" onclick="" class="arrow-right-on"></a>
-                                <div class="clearer"></div>
-                            </div><!-- end app-list container -->
-                        </div><!-- end carouselWheel -->
-                    </div><!-- end homeMiddle -->
-
-                    <div style="clear:both">&nbsp;</div>
-              </div><!-- end mainBodyLeft -->
-
-              <div id="mainBodyRight">
-                      <table id="rightColumn">
-                              <tr>
-                                      <td class="imageCell"><a href="{@docRoot}sdk/index.html"><img src="{@docRoot}assets/images/icon_download.jpg" style="padding:0" /></a></td>
-                                      <td>
-                                              <h2 class="green">ダウンロード</h2>
-                                              <p>Android SDK には、優れたアプリケーションの作成に必要となるツール、サンプル コード、ドキュメントが含まれています。  </p>
-                                              <p><a href="{@docRoot}sdk/index.html">詳細 &raquo;</a></p>
-                                      </td>
-                              </tr>
-                              <tr>
-                                      <td colspan="2"><div class="seperator">&nbsp;</div></td>
-                              </tr>
-                              <tr>
-                                      <td class="imageCell"><a href="http://play.google.com/apps/publish"><img src="{@docRoot}assets/images/icon_play.png" style="padding:0" /></a></td>
-                                      <td>
-                                              <h2 class="green">公開</h2>
-                                              <p>Android マーケットは、アプリケーションを携帯端末に配信するためのオープン サービスです。</p>
-                                              <p><a href="http://play.google.com/apps/publish">詳細 &raquo;</a></p>
-                                      </td>
-                              </tr>
-                              <tr>
-                                      <td colspan="2"><div class="seperator">&nbsp;</div></td>
-                              </tr>
-                              <tr>
-                                      <td class="imageCell"><a href="http://source.android.com"><img src="{@docRoot}assets/images/icon_contribute.jpg" style="padding:0" /></a></td>
-                                      <td>
-                                              <h2 class="green">貢献</h2>
-                                              <p>Android オープンソース プロジェクトでは、プラットフォーム全体のソースコードを公開しています。</p>
-                                              <p><a href="http://source.android.com">詳細 &raquo;</a></p>
-                                      </td>
-                              </tr>
-                              <tr>
-                                      <td colspan="2"><div class="seperator">&nbsp;</div></td>
-                              </tr>
-                              <tr>
-                                      <td class="imageCell"><a href="http://www.youtube.com/user/androiddevelopers"><img src="{@docRoot}assets/images/video-droid.png" style="padding:0" /></a></td>
-                                      <td>
-                                              <h2 class="green">再生</h2>
-                                              <object width="150" height="140"><param name="movie" value="http://www.youtube.com/v/GARMe7Km_gk&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/GARMe7Km_gk&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="150" height="140"></embed></object>
-                                              <p style="margin-top:1em"><a href="{@docRoot}videos/index.html">その他の Android 動画 &raquo;</a></p>
-                                      </td>
-                              </tr>
-
-                      </table>
-              </div>
-	</div>
-
-<!--[if lte IE 6]>
-  <style>
-    #arrow-left {
-      margin:0 0 0 5px;
-    }
-    #arrow-right {
-      margin-left:0;
-    }
-    .app-list-container {
-      margin: 37px 0 0 23px;
-    }
-    div#list-clip { 
-      width:468px;
-    }
-  </style>
-<![endif]-->
-
-<script type="text/javascript">
-
-// * -- carousel dictionary -- * //
-  /* layout:  imgLeft, imgRight, imgTop
-     icon:    image for carousel entry. cropped (height:70px, width:90px)
-     name:    string for carousel entry
-     img:     image for bulletin post. cropped (height: 170, width:230px)
-     title:   header for bulletin (optional, insert "" value to skip
-     desc:    the bulletin post. must include html tags. 
-  */
-
-  var droidList = {
-    'sdk': {
-      'layout':"imgLeft",
-      'icon':"sdk-small.png",
-      'name':"Android 2.0",
-      'img':"eclair-android.png",
-      'title':"Android 2.0",
-      'desc': "<p>Android 2.0 の最新バージョンが公開されました。このリリースには Android 2.0 用の API、最新版デベロッパーツール、複数プラットフォーム(バージョン)サポート、そして Google API のアドオンが含まれています。</p><p><a href='{@docRoot}sdk/index.html'>Android SDK をダウンロード &raquo;</a></p>"
-    },
-    
-    'io': {
-      'layout':"imgLeft",
-      'icon':"io-small.png",
-      'name':"Google I/O",
-      'img':"io-large.png",
-      'title':"Google I/O Developer Conference",
-      'desc': "<p>Google I/O は、サンフランシスコの Moscone Center で 5 月 27~28 日に開催された開発者会議です。このイベントに参加できなかった方は、各アンドロイド向けセッションを、YouTube ビデオ資料で体験する事が可能<nobr>です</nobr>。</p><p><a href='{@docRoot}videos/index.html'>セッションを参照してください &raquo;</a></p>"
-    },
-
-    'mapskey': {
-      'layout':"imgLeft",
-      'icon':"maps-small.png",
-      'name':"Maps API キー",
-      'img':"maps-large.png",
-      'title':"Maps API キー",
-      'desc':"<p>MapView から Google マップを利用する Android アプリケーションを開発する場合は、アプリケーションを登録して Maps API キーを取得する必要があります。この API キーが無いアプリケーションは、Android 上で動作しません。キーの取得は、簡単な手順で行うことができます。</p><p><a href='http://code.google.com/android/add-ons/google-apis/maps-overview.html'>詳細 &raquo;</a></p>"
-    },
-
-    'devphone': {
-      'layout':"imgLeft",
-      'icon':"devphone-small.png",
-      'name':"Dev Phone 1",
-      'img':"devphone-large.png",
-      'title':"Android Dev Phone 1",
-      'desc': "<p>この携帯電話を使用することで、開発した Android アプリケーションの実行とデバッグを行うことができます。Android オペレーティングシステムを変更してからリビルドし、携帯電話に書き込むことができます。Android Dev Phone 1 は携帯通信会社に依存しておらず、<a href='http://play.google.com/apps/publish'>Android マーケット</a>に登録済みのデベロッパーなら誰でも購入可能です。</p><p><a href='/tools/device.html#dev-phone-1'>Android Dev Phone 1 の詳細&raquo;</a></p>"
-    }
-
-  }
-</script>
-<script type="text/javascript" src="{@docRoot}assets/carousel.js"></script>
-<script type="text/javascript">
-  initCarousel("sdk");
-</script>
diff --git a/drm/jni/Android.mk b/drm/jni/Android.mk
index f8ecc8c..fff7eee 100644
--- a/drm/jni/Android.mk
+++ b/drm/jni/Android.mk
@@ -35,7 +35,8 @@
     $(JNI_H_INCLUDE) \
     $(TOP)/frameworks/av/drm/libdrmframework/include \
     $(TOP)/frameworks/av/drm/libdrmframework/plugins/common/include \
-    $(TOP)/frameworks/av/include
+    $(TOP)/frameworks/av/include \
+    $(TOP)/libcore/include
 
 
 
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index 14ec4d6..fb685a2 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -20,6 +20,7 @@
 
 #include <jni.h>
 #include <JNIHelp.h>
+#include <ScopedLocalRef.h>
 #include <android_runtime/AndroidRuntime.h>
 
 #include <drm/DrmInfo.h>
@@ -250,16 +251,18 @@
         = getDrmManagerClientImpl(env, thiz)->getConstraints(uniqueId, &pathString, usage);
 
     jclass localRef = env->FindClass("android/content/ContentValues");
+    jmethodID ContentValues_putByteArray =
+            env->GetMethodID(localRef, "put", "(Ljava/lang/String;[B)V");
+    jmethodID ContentValues_putString =
+            env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V");
+    jmethodID ContentValues_constructor = env->GetMethodID(localRef, "<init>", "()V");
     jobject constraints = NULL;
 
     if (NULL != localRef && NULL != pConstraints) {
-        // Get the constructor id
-        jmethodID constructorId = env->GetMethodID(localRef, "<init>", "()V");
         // create the java DrmConstraints object
-        constraints = env->NewObject(localRef, constructorId);
+        constraints = env->NewObject(localRef, ContentValues_constructor);
 
         DrmConstraints::KeyIterator keyIt = pConstraints->keyIterator();
-
         while (keyIt.hasNext()) {
             String8 key = keyIt.next();
 
@@ -267,18 +270,18 @@
             if (DrmConstraints::EXTENDED_METADATA == key) {
                 const char* value = pConstraints->getAsByteArray(&key);
                 if (NULL != value) {
-                    jbyteArray dataArray = env->NewByteArray(strlen(value));
-                    env->SetByteArrayRegion(dataArray, 0, strlen(value), (jbyte*)value);
-                    env->CallVoidMethod(
-                        constraints, env->GetMethodID(localRef, "put", "(Ljava/lang/String;[B)V"),
-                                     env->NewStringUTF(key.string()), dataArray);
+                    ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(strlen(value)));
+                    ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
+                    env->SetByteArrayRegion(dataArray.get(), 0, strlen(value), (jbyte*)value);
+                    env->CallVoidMethod(constraints, ContentValues_putByteArray,
+                                        keyString.get(), dataArray.get());
                 }
             } else {
                 String8 value = pConstraints->get(key);
-                env->CallVoidMethod(
-                    constraints,
-                    env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V"),
-                env->NewStringUTF(key.string()), env->NewStringUTF(value.string()));
+                ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
+                ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
+                env->CallVoidMethod(constraints, ContentValues_putString,
+                                    keyString.get(), valueString.get());
             }
         }
     }
@@ -297,8 +300,10 @@
 
     jobject metadata = NULL;
 
-    jclass localRef = NULL;
-    localRef = env->FindClass("android/content/ContentValues");
+    jclass localRef = env->FindClass("android/content/ContentValues");
+    jmethodID ContentValues_putString =
+            env->GetMethodID(localRef, "put", "(Ljava/lang/String;Ljava/lang/String;)V");
+
     if (NULL != localRef && NULL != pMetadata) {
         // Get the constructor id
         jmethodID constructorId = NULL;
@@ -313,9 +318,10 @@
                     // insert the entry<constraintKey, constraintValue>
                     // to newly created java object
                     String8 value = pMetadata->get(key);
-                    env->CallVoidMethod(metadata, env->GetMethodID(localRef, "put",
-                            "(Ljava/lang/String;Ljava/lang/String;)V"),
-                    env->NewStringUTF(key.string()), env->NewStringUTF(value.string()));
+                    ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
+                    ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
+                    env->CallVoidMethod(metadata, ContentValues_putString,
+                                        keyString.get(), valueString.get());
                 }
             }
         }
@@ -426,29 +432,30 @@
     DrmInfo drmInfo(mInfoType, buffer, mMimeType);
 
     jclass clazz = env->FindClass("android/drm/DrmInfo");
+    jmethodID DrmInfo_get = env->GetMethodID(clazz, "get", "(Ljava/lang/String;)Ljava/lang/Object;");
     jobject keyIterator
         = env->CallObjectMethod(drmInfoObject,
                 env->GetMethodID(clazz, "keyIterator", "()Ljava/util/Iterator;"));
 
-    jmethodID hasNextId = env->GetMethodID(env->FindClass("java/util/Iterator"), "hasNext", "()Z");
+    jclass Iterator_class = env->FindClass("java/util/Iterator");
+    jmethodID Iterator_hasNext = env->GetMethodID(Iterator_class, "hasNext", "()Z");
+    jmethodID Iterator_next = env->GetMethodID(Iterator_class, "next", "()Ljava/lang/Object;");
 
-    while (env->CallBooleanMethod(keyIterator, hasNextId)) {
-        jstring key = (jstring) env->CallObjectMethod(keyIterator,
-                env->GetMethodID(env->FindClass("java/util/Iterator"),
-                "next", "()Ljava/lang/Object;"));
+    jclass Object_class = env->FindClass("java/lang/Object");
+    jmethodID Object_toString = env->GetMethodID(Object_class, "toString", "()Ljava/lang/String;");
 
-        jobject valueObject = env->CallObjectMethod(drmInfoObject,
-                env->GetMethodID(clazz, "get", "(Ljava/lang/String;)Ljava/lang/Object;"), key);
-
-        jstring valString = NULL;
-        if (NULL != valueObject) {
-            valString = (jstring) env->CallObjectMethod(valueObject,
-                env->GetMethodID(env->FindClass("java/lang/Object"),
-                "toString", "()Ljava/lang/String;"));
+    while (env->CallBooleanMethod(keyIterator, Iterator_hasNext)) {
+        ScopedLocalRef<jstring> key(env,
+                (jstring) env->CallObjectMethod(keyIterator, Iterator_next));
+        ScopedLocalRef<jobject> valueObject(env,
+                env->CallObjectMethod(drmInfoObject, DrmInfo_get, key.get()));
+        ScopedLocalRef<jstring> valString(env, NULL);
+        if (NULL != valueObject.get()) {
+            valString.reset((jstring) env->CallObjectMethod(valueObject.get(), Object_toString));
         }
 
-        String8 keyString = Utility::getStringValue(env, key);
-        String8 valueString = Utility::getStringValue(env, valString);
+        String8 keyString = Utility::getStringValue(env, key.get());
+        String8 valueString = Utility::getStringValue(env, valString.get());
         ALOGV("Key: %s | Value: %s", keyString.string(), valueString.string());
 
         drmInfo.put(keyString, valueString);
@@ -508,20 +515,21 @@
     jobject keyIterator
         = env->CallObjectMethod(drmInfoRequest,
                 env->GetMethodID(clazz, "keyIterator", "()Ljava/util/Iterator;"));
+    jmethodID DrmInfoRequest_get = env->GetMethodID(clazz,
+            "get", "(Ljava/lang/String;)Ljava/lang/Object;");
 
-    jmethodID hasNextId = env->GetMethodID(env->FindClass("java/util/Iterator"), "hasNext", "()Z");
+    jclass Iterator_class = env->FindClass("java/util/Iterator");
+    jmethodID Iterator_hasNext = env->GetMethodID(Iterator_class, "hasNext", "()Z");
+    jmethodID Iterator_next = env->GetMethodID(Iterator_class, "next", "()Ljava/lang/Object;");
 
-    while (env->CallBooleanMethod(keyIterator, hasNextId)) {
-        jstring key
-            = (jstring) env->CallObjectMethod(keyIterator,
-                env->GetMethodID(env->FindClass("java/util/Iterator"),
-                                "next", "()Ljava/lang/Object;"));
+    while (env->CallBooleanMethod(keyIterator, Iterator_hasNext)) {
+        ScopedLocalRef<jstring> key(env,
+                (jstring) env->CallObjectMethod(keyIterator, Iterator_next));
+        ScopedLocalRef<jstring> value(env,
+                (jstring) env->CallObjectMethod(drmInfoRequest, DrmInfoRequest_get, key.get()));
 
-        jstring value = (jstring) env->CallObjectMethod(drmInfoRequest,
-                env->GetMethodID(clazz, "get", "(Ljava/lang/String;)Ljava/lang/Object;"), key);
-
-        String8 keyString = Utility::getStringValue(env, key);
-        String8 valueString = Utility::getStringValue(env, value);
+        String8 keyString = Utility::getStringValue(env, key.get());
+        String8 valueString = Utility::getStringValue(env, value.get());
         ALOGV("Key: %s | Value: %s", keyString.string(), valueString.string());
 
         drmInfoReq.put(keyString, valueString);
@@ -552,9 +560,10 @@
             while (it.hasNext()) {
                 String8 key = it.next();
                 String8 value = pDrmInfo->get(key);
-
+                ScopedLocalRef<jstring> keyString(env, env->NewStringUTF(key.string()));
+                ScopedLocalRef<jstring> valueString(env, env->NewStringUTF(value.string()));
                 env->CallVoidMethod(drmInfoObject, putMethodId,
-                    env->NewStringUTF(key.string()), env->NewStringUTF(value.string()));
+                    keyString.get(), valueString.get());
             }
         }
         delete [] pDrmInfo->getData().data;
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
new file mode 100644
index 0000000..a629f8d
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2012 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.security;
+
+import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
+
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyStoreException;
+import java.security.KeyStoreSpi;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A java.security.KeyStore interface for the Android KeyStore. This class is
+ * hidden from the Android API, but an instance of it can be created via the
+ * {@link java.security.KeyStore#getInstance(String)
+ * KeyStore.getInstance("AndroidKeyStore")} interface. This returns a
+ * java.security.KeyStore backed by this "AndroidKeyStore" implementation.
+ * <p>
+ * This is built on top of Android's keystore daemon. The convention of alias
+ * use is:
+ * <p>
+ * PrivateKeyEntry will have a Credentials.USER_PRIVATE_KEY as the private key,
+ * Credentials.USER_CERTIFICATE as the first certificate in the chain (the one
+ * that corresponds to the private key), and then a Credentials.CA_CERTIFICATE
+ * entry which will have the rest of the chain concatenated in BER format.
+ * <p>
+ * TrustedCertificateEntry will just have a Credentials.CA_CERTIFICATE entry
+ * with a single certificate.
+ *
+ * @hide
+ */
+public class AndroidKeyStore extends KeyStoreSpi {
+    public static final String NAME = "AndroidKeyStore";
+
+    private android.security.KeyStore mKeyStore;
+
+    @Override
+    public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
+            UnrecoverableKeyException {
+        if (!isKeyEntry(alias)) {
+            return null;
+        }
+
+        final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+        try {
+            return engine.getPrivateKeyById(Credentials.USER_PRIVATE_KEY + alias);
+        } catch (InvalidKeyException e) {
+            UnrecoverableKeyException t = new UnrecoverableKeyException("Can't get key");
+            t.initCause(e);
+            throw t;
+        }
+    }
+
+    @Override
+    public Certificate[] engineGetCertificateChain(String alias) {
+        final X509Certificate leaf = (X509Certificate) engineGetCertificate(alias);
+        if (leaf == null) {
+            return null;
+        }
+
+        final Certificate[] caList;
+
+        final byte[] caBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+        if (caBytes != null) {
+            final Collection<X509Certificate> caChain = toCertificates(caBytes);
+
+            caList = new Certificate[caChain.size() + 1];
+
+            final Iterator<X509Certificate> it = caChain.iterator();
+            int i = 1;
+            while (it.hasNext()) {
+                caList[i++] = it.next();
+            }
+        } else {
+            caList = new Certificate[1];
+        }
+
+        caList[0] = leaf;
+
+        return caList;
+    }
+
+    @Override
+    public Certificate engineGetCertificate(String alias) {
+        byte[] certificate = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+        if (certificate != null) {
+            return toCertificate(certificate);
+        }
+
+        certificate = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+        if (certificate != null) {
+            return toCertificate(certificate);
+        }
+
+        return null;
+    }
+
+    private static X509Certificate toCertificate(byte[] bytes) {
+        try {
+            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            return (X509Certificate) certFactory
+                    .generateCertificate(new ByteArrayInputStream(bytes));
+        } catch (CertificateException e) {
+            Log.w(NAME, "Couldn't parse certificate in keystore", e);
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Collection<X509Certificate> toCertificates(byte[] bytes) {
+        try {
+            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            return (Collection<X509Certificate>) certFactory
+                    .generateCertificates(new ByteArrayInputStream(bytes));
+        } catch (CertificateException e) {
+            Log.w(NAME, "Couldn't parse certificates in keystore", e);
+            return new ArrayList<X509Certificate>();
+        }
+    }
+
+    private Date getModificationDate(String alias) {
+        final long epochMillis = mKeyStore.getmtime(alias);
+        if (epochMillis == -1L) {
+            return null;
+        }
+
+        return new Date(epochMillis);
+    }
+
+    @Override
+    public Date engineGetCreationDate(String alias) {
+        Date d = getModificationDate(Credentials.USER_PRIVATE_KEY + alias);
+        if (d != null) {
+            return d;
+        }
+
+        d = getModificationDate(Credentials.USER_CERTIFICATE + alias);
+        if (d != null) {
+            return d;
+        }
+
+        return getModificationDate(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain)
+            throws KeyStoreException {
+        if ((password != null) && (password.length > 0)) {
+            throw new KeyStoreException("entries cannot be protected with passwords");
+        }
+
+        if (key instanceof PrivateKey) {
+            setPrivateKeyEntry(alias, (PrivateKey) key, chain);
+        } else {
+            throw new KeyStoreException("Only PrivateKeys are supported");
+        }
+    }
+
+    private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain)
+            throws KeyStoreException {
+        // Make sure the PrivateKey format is the one we support.
+        final String keyFormat = key.getFormat();
+        if ((keyFormat == null) || (!"PKCS#8".equals(keyFormat))) {
+            throw new KeyStoreException(
+                    "Only PrivateKeys that can be encoded into PKCS#8 are supported");
+        }
+
+        // Make sure we can actually encode the key.
+        final byte[] keyBytes = key.getEncoded();
+        if (keyBytes == null) {
+            throw new KeyStoreException("PrivateKey has no encoding");
+        }
+
+        // Make sure the chain exists since this is a PrivateKey
+        if ((chain == null) || (chain.length == 0)) {
+            throw new KeyStoreException("Must supply at least one Certificate with PrivateKey");
+        }
+
+        // Do chain type checking.
+        X509Certificate[] x509chain = new X509Certificate[chain.length];
+        for (int i = 0; i < chain.length; i++) {
+            if (!"X.509".equals(chain[i].getType())) {
+                throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
+                        + i);
+            }
+
+            if (!(chain[i] instanceof X509Certificate)) {
+                throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
+                        + i);
+            }
+
+            x509chain[i] = (X509Certificate) chain[i];
+        }
+
+        final byte[] userCertBytes;
+        try {
+            userCertBytes = x509chain[0].getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new KeyStoreException("Couldn't encode certificate #1", e);
+        }
+
+        /*
+         * If we have a chain, store it in the CA certificate slot for this
+         * alias as concatenated DER-encoded certificates. These can be
+         * deserialized by {@link CertificateFactory#generateCertificates}.
+         */
+        final byte[] chainBytes;
+        if (chain.length > 1) {
+            /*
+             * The chain is passed in as {user_cert, ca_cert_1, ca_cert_2, ...}
+             * so we only need the certificates starting at index 1.
+             */
+            final byte[][] certsBytes = new byte[x509chain.length - 1][];
+            int totalCertLength = 0;
+            for (int i = 0; i < certsBytes.length; i++) {
+                try {
+                    certsBytes[i] = x509chain[i + 1].getEncoded();
+                    totalCertLength += certsBytes[i].length;
+                } catch (CertificateEncodingException e) {
+                    throw new KeyStoreException("Can't encode Certificate #" + i, e);
+                }
+            }
+
+            /*
+             * Serialize this into one byte array so we can later call
+             * CertificateFactory#generateCertificates to recover them.
+             */
+            chainBytes = new byte[totalCertLength];
+            int outputOffset = 0;
+            for (int i = 0; i < certsBytes.length; i++) {
+                final int certLength = certsBytes[i].length;
+                System.arraycopy(certsBytes[i], 0, chainBytes, outputOffset, certLength);
+                outputOffset += certLength;
+                certsBytes[i] = null;
+            }
+        } else {
+            chainBytes = null;
+        }
+
+        /*
+         * Make sure we clear out all the types we know about before trying to
+         * write.
+         */
+        deleteAllTypesForAlias(alias);
+
+        if (!mKeyStore.importKey(Credentials.USER_PRIVATE_KEY + alias, keyBytes)) {
+            throw new KeyStoreException("Couldn't put private key in keystore");
+        } else if (!mKeyStore.put(Credentials.USER_CERTIFICATE + alias, userCertBytes)) {
+            throw new KeyStoreException("Couldn't put certificate #1 in keystore");
+        } else if (chainBytes != null
+                && !mKeyStore.put(Credentials.CA_CERTIFICATE + alias, chainBytes)) {
+            throw new KeyStoreException("Couldn't put certificate chain in keystore");
+        }
+    }
+
+    @Override
+    public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
+            throws KeyStoreException {
+        throw new RuntimeException("Operation not supported because key encoding is unknown");
+    }
+
+    @Override
+    public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
+        if (isKeyEntry(alias)) {
+            throw new KeyStoreException("Entry exists and is not a trusted certificate");
+        }
+
+        final byte[] encoded;
+        try {
+            encoded = cert.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new KeyStoreException(e);
+        }
+
+        if (!mKeyStore.put(Credentials.CA_CERTIFICATE + alias, encoded)) {
+            throw new KeyStoreException("Couldn't insert certificate; is KeyStore initialized?");
+        }
+    }
+
+    @Override
+    public void engineDeleteEntry(String alias) throws KeyStoreException {
+        if (!deleteAllTypesForAlias(alias)) {
+            throw new KeyStoreException("No such entry " + alias);
+        }
+    }
+
+    /**
+     * Delete all types (private key, certificate, CA certificate) for a
+     * particular {@code alias}. All three can exist for any given alias.
+     * Returns {@code true} if there was at least one of those types.
+     */
+    private boolean deleteAllTypesForAlias(String alias) {
+        /*
+         * Make sure every type is deleted. There can be all three types, so
+         * don't use a conditional here.
+         */
+        return mKeyStore.delKey(Credentials.USER_PRIVATE_KEY + alias)
+                | mKeyStore.delete(Credentials.USER_CERTIFICATE + alias)
+                | mKeyStore.delete(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    private Set<String> getUniqueAliases() {
+        final String[] rawAliases = mKeyStore.saw("");
+        if (rawAliases == null) {
+            return new HashSet<String>();
+        }
+
+        final Set<String> aliases = new HashSet<String>(rawAliases.length);
+        for (String alias : rawAliases) {
+            final int idx = alias.indexOf('_');
+            if ((idx == -1) || (alias.length() <= idx)) {
+                Log.e(NAME, "invalid alias: " + alias);
+                continue;
+            }
+
+            aliases.add(new String(alias.substring(idx + 1)));
+        }
+
+        return aliases;
+    }
+
+    @Override
+    public Enumeration<String> engineAliases() {
+        return Collections.enumeration(getUniqueAliases());
+    }
+
+    @Override
+    public boolean engineContainsAlias(String alias) {
+        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias)
+                || mKeyStore.contains(Credentials.USER_CERTIFICATE + alias)
+                || mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public int engineSize() {
+        return getUniqueAliases().size();
+    }
+
+    @Override
+    public boolean engineIsKeyEntry(String alias) {
+        return isKeyEntry(alias);
+    }
+
+    private boolean isKeyEntry(String alias) {
+        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias);
+    }
+
+    @Override
+    public boolean engineIsCertificateEntry(String alias) {
+        return !isKeyEntry(alias) && mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+    }
+
+    @Override
+    public String engineGetCertificateAlias(Certificate cert) {
+        if (cert == null) {
+            return null;
+        }
+
+        final Set<String> nonCaEntries = new HashSet<String>();
+
+        /*
+         * First scan the PrivateKeyEntry types. The KeyStoreSpi documentation
+         * says to only compare the first certificate in the chain which is
+         * equivalent to the USER_CERTIFICATE prefix for the Android keystore
+         * convention.
+         */
+        final String[] certAliases = mKeyStore.saw(Credentials.USER_CERTIFICATE);
+        for (String alias : certAliases) {
+            final byte[] certBytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+            if (certBytes == null) {
+                continue;
+            }
+
+            final Certificate c = toCertificate(certBytes);
+            nonCaEntries.add(alias);
+
+            if (cert.equals(c)) {
+                return alias;
+            }
+        }
+
+        /*
+         * Look at all the TrustedCertificateEntry types. Skip all the
+         * PrivateKeyEntry we looked at above.
+         */
+        final String[] caAliases = mKeyStore.saw(Credentials.CA_CERTIFICATE);
+        for (String alias : caAliases) {
+            if (nonCaEntries.contains(alias)) {
+                continue;
+            }
+
+            final byte[] certBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+            if (certBytes == null) {
+                continue;
+            }
+
+            final Certificate c = toCertificate(mKeyStore.get(Credentials.CA_CERTIFICATE + alias));
+            if (cert.equals(c)) {
+                return alias;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void engineStore(OutputStream stream, char[] password) throws IOException,
+            NoSuchAlgorithmException, CertificateException {
+        throw new UnsupportedOperationException("Can not serialize AndroidKeyStore to OutputStream");
+    }
+
+    @Override
+    public void engineLoad(InputStream stream, char[] password) throws IOException,
+            NoSuchAlgorithmException, CertificateException {
+        if (stream != null) {
+            throw new IllegalArgumentException("InputStream not supported");
+        }
+
+        if (password != null) {
+            throw new IllegalArgumentException("password not supported");
+        }
+
+        // Unfortunate name collision.
+        mKeyStore = android.security.KeyStore.getInstance();
+    }
+
+}
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java
new file mode 100644
index 0000000..df22f58
--- /dev/null
+++ b/keystore/java/android/security/AndroidKeyStoreProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 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.security;
+
+import java.security.Provider;
+
+/**
+ * A provider focused on providing JCA interfaces for the Android KeyStore.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreProvider extends Provider {
+    public static final String PROVIDER_NAME = "AndroidKeyStoreProvider";
+
+    public AndroidKeyStoreProvider() {
+        super(PROVIDER_NAME, 1.0, "Android KeyStore security provider");
+
+        put("KeyStore." + AndroidKeyStore.NAME, AndroidKeyStore.class.getName());
+    }
+}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index f49c429..4637991 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -26,6 +26,7 @@
 import java.nio.charset.Charsets;
 import java.nio.charset.ModifiedUtf8;
 import java.util.ArrayList;
+import java.util.Date;
 
 /**
  * @hide This should not be made public in its present form because it
@@ -228,6 +229,23 @@
         return ungrant(getKeyBytes(key), getUidBytes(uid));
     }
 
+    private long getmtime(byte[] key) {
+        final ArrayList<byte[]> values = execute('c', key);
+        if (values == null || values.isEmpty()) {
+            return -1L;
+        }
+
+        return Long.parseLong(new String(values.get(0))) * 1000L;
+    }
+
+    /**
+     * Returns the last modification time of the key in milliseconds since the
+     * epoch. Will return -1L if the key could not be found or other error.
+     */
+    public long getmtime(String key) {
+        return getmtime(getKeyBytes(key));
+    }
+
     public int getLastError() {
         return mError;
     }
diff --git a/keystore/tests/src/android/security/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
new file mode 100644
index 0000000..bff01b8
--- /dev/null
+++ b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
@@ -0,0 +1,1383 @@
+/*
+ * Copyright (C) 2012 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.security;
+
+import android.test.AndroidTestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyStore.Entry;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStore.TrustedCertificateEntry;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class AndroidKeyStoreTest extends AndroidTestCase {
+    private android.security.KeyStore mAndroidKeyStore;
+
+    private java.security.KeyStore mKeyStore;
+
+    private static final String TEST_ALIAS_1 = "test1";
+
+    private static final String TEST_ALIAS_2 = "test2";
+
+    private static final String TEST_ALIAS_3 = "test3";
+
+    /*
+     * The keys and certificates below are generated with:
+     *
+     * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
+     * openssl req -newkey rsa:1024 -keyout userkey.pem -nodes -days 3650 -out userkey.req
+     * mkdir -p demoCA/newcerts
+     * touch demoCA/index.txt
+     * echo "01" > demoCA/serial
+     * openssl ca -out usercert.pem -in userkey.req -cert cacert.pem -keyfile cakey.pem -days 3650
+     */
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in cacert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_CA_1 = {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xce, (byte) 0x30, (byte) 0x82,
+            (byte) 0x02, (byte) 0x37, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+            (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0xe1, (byte) 0x6a,
+            (byte) 0xa2, (byte) 0xf4, (byte) 0x2e, (byte) 0x55, (byte) 0x48, (byte) 0x0a,
+            (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+            (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+            (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53,
+            (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43,
+            (byte) 0x41, (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d,
+            (byte) 0x4d, (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61,
+            (byte) 0x69, (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65,
+            (byte) 0x77, (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12,
+            (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69,
+            (byte) 0x64, (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
+            (byte) 0x20, (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73,
+            (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32,
+            (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x34, (byte) 0x31, (byte) 0x36,
+            (byte) 0x35, (byte) 0x35, (byte) 0x34, (byte) 0x34, (byte) 0x5a, (byte) 0x17,
+            (byte) 0x0d, (byte) 0x32, (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31,
+            (byte) 0x32, (byte) 0x31, (byte) 0x36, (byte) 0x35, (byte) 0x35, (byte) 0x34,
+            (byte) 0x34, (byte) 0x5a, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41,
+            (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d,
+            (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69,
+            (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77,
+            (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41,
+            (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64,
+            (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20,
+            (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30,
+            (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+            (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+            (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+            (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89,
+            (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xa3, (byte) 0x72,
+            (byte) 0xab, (byte) 0xd0, (byte) 0xe4, (byte) 0xad, (byte) 0x2f, (byte) 0xe7,
+            (byte) 0xe2, (byte) 0x79, (byte) 0x07, (byte) 0x36, (byte) 0x3d, (byte) 0x0c,
+            (byte) 0x8d, (byte) 0x42, (byte) 0x9a, (byte) 0x0a, (byte) 0x33, (byte) 0x64,
+            (byte) 0xb3, (byte) 0xcd, (byte) 0xb2, (byte) 0xd7, (byte) 0x3a, (byte) 0x42,
+            (byte) 0x06, (byte) 0x77, (byte) 0x45, (byte) 0x29, (byte) 0xe9, (byte) 0xcb,
+            (byte) 0xb7, (byte) 0x4a, (byte) 0xd6, (byte) 0xee, (byte) 0xad, (byte) 0x01,
+            (byte) 0x91, (byte) 0x9b, (byte) 0x0c, (byte) 0x59, (byte) 0xa1, (byte) 0x03,
+            (byte) 0xfa, (byte) 0xf0, (byte) 0x5a, (byte) 0x7c, (byte) 0x4f, (byte) 0xf7,
+            (byte) 0x8d, (byte) 0x36, (byte) 0x0f, (byte) 0x1f, (byte) 0x45, (byte) 0x7d,
+            (byte) 0x1b, (byte) 0x31, (byte) 0xa1, (byte) 0x35, (byte) 0x0b, (byte) 0x00,
+            (byte) 0xed, (byte) 0x7a, (byte) 0xb6, (byte) 0xc8, (byte) 0x4e, (byte) 0xa9,
+            (byte) 0x86, (byte) 0x4c, (byte) 0x7b, (byte) 0x99, (byte) 0x57, (byte) 0x41,
+            (byte) 0x12, (byte) 0xef, (byte) 0x6b, (byte) 0xbc, (byte) 0x3d, (byte) 0x60,
+            (byte) 0xf2, (byte) 0x99, (byte) 0x1a, (byte) 0xcd, (byte) 0xed, (byte) 0x56,
+            (byte) 0xa4, (byte) 0xe5, (byte) 0x36, (byte) 0x9f, (byte) 0x24, (byte) 0x1f,
+            (byte) 0xdc, (byte) 0x89, (byte) 0x40, (byte) 0xc8, (byte) 0x99, (byte) 0x92,
+            (byte) 0xab, (byte) 0x4a, (byte) 0xb5, (byte) 0x61, (byte) 0x45, (byte) 0x62,
+            (byte) 0xff, (byte) 0xa3, (byte) 0x45, (byte) 0x65, (byte) 0xaf, (byte) 0xf6,
+            (byte) 0x27, (byte) 0x30, (byte) 0x51, (byte) 0x0e, (byte) 0x0e, (byte) 0xeb,
+            (byte) 0x79, (byte) 0x0c, (byte) 0xbe, (byte) 0xb3, (byte) 0x0a, (byte) 0x6f,
+            (byte) 0x29, (byte) 0x06, (byte) 0xdc, (byte) 0x2f, (byte) 0x6b, (byte) 0x51,
+            (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3,
+            (byte) 0x81, (byte) 0xb1, (byte) 0x30, (byte) 0x81, (byte) 0xae, (byte) 0x30,
+            (byte) 0x1d, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e,
+            (byte) 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x33, (byte) 0x05,
+            (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60, (byte) 0xc7, (byte) 0xf9,
+            (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c, (byte) 0x8f, (byte) 0x6d,
+            (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e, (byte) 0x5d, (byte) 0x51,
+            (byte) 0x30, (byte) 0x7f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d,
+            (byte) 0x23, (byte) 0x04, (byte) 0x78, (byte) 0x30, (byte) 0x76, (byte) 0x80,
+            (byte) 0x14, (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f,
+            (byte) 0x60, (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73,
+            (byte) 0x5c, (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97,
+            (byte) 0x8e, (byte) 0x5d, (byte) 0x51, (byte) 0xa1, (byte) 0x53, (byte) 0xa4,
+            (byte) 0x51, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+            (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+            (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+            (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+            (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+            (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+            (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+            (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+            (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x82, (byte) 0x09,
+            (byte) 0x00, (byte) 0xe1, (byte) 0x6a, (byte) 0xa2, (byte) 0xf4, (byte) 0x2e,
+            (byte) 0x55, (byte) 0x48, (byte) 0x0a, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x05,
+            (byte) 0x30, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30,
+            (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
+            (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+            (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x81, (byte) 0x00,
+            (byte) 0x8c, (byte) 0x30, (byte) 0x42, (byte) 0xfa, (byte) 0xeb, (byte) 0x1a,
+            (byte) 0x26, (byte) 0xeb, (byte) 0xda, (byte) 0x56, (byte) 0x32, (byte) 0xf2,
+            (byte) 0x9d, (byte) 0xa5, (byte) 0x24, (byte) 0xd8, (byte) 0x3a, (byte) 0xda,
+            (byte) 0x30, (byte) 0xa6, (byte) 0x8b, (byte) 0x46, (byte) 0xfe, (byte) 0xfe,
+            (byte) 0xdb, (byte) 0xf1, (byte) 0xe6, (byte) 0xe1, (byte) 0x7c, (byte) 0x1b,
+            (byte) 0xe7, (byte) 0x77, (byte) 0x00, (byte) 0xa1, (byte) 0x1c, (byte) 0x19,
+            (byte) 0x17, (byte) 0x73, (byte) 0xb0, (byte) 0xf0, (byte) 0x9d, (byte) 0xf3,
+            (byte) 0x4f, (byte) 0xb6, (byte) 0xbc, (byte) 0xc7, (byte) 0x47, (byte) 0x85,
+            (byte) 0x2a, (byte) 0x4a, (byte) 0xa1, (byte) 0xa5, (byte) 0x58, (byte) 0xf5,
+            (byte) 0xc5, (byte) 0x1a, (byte) 0x51, (byte) 0xb1, (byte) 0x04, (byte) 0x80,
+            (byte) 0xee, (byte) 0x3a, (byte) 0xec, (byte) 0x2f, (byte) 0xe1, (byte) 0xfd,
+            (byte) 0x58, (byte) 0xeb, (byte) 0xed, (byte) 0x82, (byte) 0x9e, (byte) 0x38,
+            (byte) 0xa3, (byte) 0x24, (byte) 0x75, (byte) 0xf7, (byte) 0x3e, (byte) 0xc2,
+            (byte) 0xc5, (byte) 0x27, (byte) 0xeb, (byte) 0x6f, (byte) 0x7b, (byte) 0x50,
+            (byte) 0xda, (byte) 0x43, (byte) 0xdc, (byte) 0x3b, (byte) 0x0b, (byte) 0x6f,
+            (byte) 0x78, (byte) 0x8f, (byte) 0xb0, (byte) 0x66, (byte) 0xe1, (byte) 0x12,
+            (byte) 0x87, (byte) 0x5f, (byte) 0x97, (byte) 0x7b, (byte) 0xca, (byte) 0x14,
+            (byte) 0x79, (byte) 0xf7, (byte) 0xe8, (byte) 0x6c, (byte) 0x72, (byte) 0xdb,
+            (byte) 0x91, (byte) 0x65, (byte) 0x17, (byte) 0x54, (byte) 0xe0, (byte) 0x74,
+            (byte) 0x1d, (byte) 0xac, (byte) 0x47, (byte) 0x04, (byte) 0x12, (byte) 0xe0,
+            (byte) 0xc3, (byte) 0x66, (byte) 0x19, (byte) 0x05, (byte) 0x2e, (byte) 0x7e,
+            (byte) 0xf1, (byte) 0x61
+    };
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_KEY_1 = new byte[] {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01,
+            (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+            (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+            (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82,
+            (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e,
+            (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81,
+            (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b,
+            (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66,
+            (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a,
+            (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02,
+            (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3,
+            (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d,
+            (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67,
+            (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb,
+            (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2,
+            (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79,
+            (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce,
+            (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08,
+            (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b,
+            (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4,
+            (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d,
+            (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23,
+            (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08,
+            (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1,
+            (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4,
+            (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16,
+            (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e,
+            (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01,
+            (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16,
+            (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98,
+            (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf,
+            (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a,
+            (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2,
+            (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc,
+            (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5,
+            (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a,
+            (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b,
+            (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9,
+            (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12,
+            (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e,
+            (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d,
+            (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2,
+            (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d,
+            (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc,
+            (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98,
+            (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96,
+            (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30,
+            (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e,
+            (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad,
+            (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f,
+            (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89,
+            (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13,
+            (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a,
+            (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e,
+            (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa,
+            (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47,
+            (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44,
+            (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22,
+            (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10,
+            (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45,
+            (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4,
+            (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda,
+            (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1,
+            (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab,
+            (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7,
+            (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc,
+            (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d,
+            (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82,
+            (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3,
+            (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a,
+            (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9,
+            (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6,
+            (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+            (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd,
+            (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb,
+            (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4,
+            (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0,
+            (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2,
+            (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce,
+            (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a,
+            (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21,
+            (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d,
+            (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1,
+            (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41,
+            (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce,
+            (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0,
+            (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40,
+            (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a,
+            (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c,
+            (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90,
+            (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf,
+            (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb,
+            (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14,
+            (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab,
+            (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02,
+            (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67,
+            (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d,
+            (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d,
+            (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b,
+            (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2,
+            (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28,
+            (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd,
+            (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d,
+            (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b,
+            (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1,
+            (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51
+    };
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_USER_1 = new byte[] {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x95, (byte) 0x30, (byte) 0x82,
+            (byte) 0x01, (byte) 0xfe, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+            (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d,
+            (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+            (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05,
+            (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+            (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+            (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+            (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+            (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+            (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+            (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+            (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+            (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30, (byte) 0x1e,
+            (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32, (byte) 0x30, (byte) 0x38,
+            (byte) 0x31, (byte) 0x34, (byte) 0x32, (byte) 0x33, (byte) 0x32, (byte) 0x35,
+            (byte) 0x34, (byte) 0x38, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, (byte) 0x32,
+            (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x32, (byte) 0x32,
+            (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x34, (byte) 0x38, (byte) 0x5a,
+            (byte) 0x30, (byte) 0x55, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13,
+            (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08,
+            (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31, (byte) 0x1b,
+            (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e, (byte) 0x64,
+            (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x54,
+            (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43, (byte) 0x61,
+            (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x31, (byte) 0x1c, (byte) 0x30,
+            (byte) 0x1a, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03,
+            (byte) 0x13, (byte) 0x13, (byte) 0x73, (byte) 0x65, (byte) 0x72, (byte) 0x76,
+            (byte) 0x65, (byte) 0x72, (byte) 0x31, (byte) 0x2e, (byte) 0x65, (byte) 0x78,
+            (byte) 0x61, (byte) 0x6d, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x2e,
+            (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30, (byte) 0x81, (byte) 0x9f,
+            (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+            (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+            (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d,
+            (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81,
+            (byte) 0x81, (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6,
+            (byte) 0x5b, (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c,
+            (byte) 0x66, (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86,
+            (byte) 0x8a, (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3,
+            (byte) 0x02, (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08,
+            (byte) 0xf3, (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04,
+            (byte) 0x6d, (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f,
+            (byte) 0x67, (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c,
+            (byte) 0xcb, (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30,
+            (byte) 0xe2, (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5,
+            (byte) 0x79, (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b,
+            (byte) 0xce, (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb,
+            (byte) 0x08, (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff,
+            (byte) 0x3b, (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9,
+            (byte) 0xc4, (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29,
+            (byte) 0x0d, (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b,
+            (byte) 0x23, (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78,
+            (byte) 0x08, (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5,
+            (byte) 0xf1, (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19,
+            (byte) 0xb4, (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03,
+            (byte) 0x16, (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce,
+            (byte) 0x9e, (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03,
+            (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30,
+            (byte) 0x79, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00,
+            (byte) 0x30, (byte) 0x2c, (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86,
+            (byte) 0x48, (byte) 0x01, (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01,
+            (byte) 0x0d, (byte) 0x04, (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f,
+            (byte) 0x70, (byte) 0x65, (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c,
+            (byte) 0x20, (byte) 0x47, (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72,
+            (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43,
+            (byte) 0x65, (byte) 0x72, (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69,
+            (byte) 0x63, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04,
+            (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x32, (byte) 0xa1, (byte) 0x1e,
+            (byte) 0x6b, (byte) 0x69, (byte) 0x04, (byte) 0xfe, (byte) 0xb3, (byte) 0xcd,
+            (byte) 0xf8, (byte) 0xbb, (byte) 0x14, (byte) 0xcd, (byte) 0xff, (byte) 0xd4,
+            (byte) 0x16, (byte) 0xc3, (byte) 0xab, (byte) 0x44, (byte) 0x2f, (byte) 0x30,
+            (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23,
+            (byte) 0x04, (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14,
+            (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60,
+            (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c,
+            (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e,
+            (byte) 0x5d, (byte) 0x51, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+            (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+            (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+            (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0x46, (byte) 0x42, (byte) 0xef,
+            (byte) 0x56, (byte) 0x89, (byte) 0x78, (byte) 0x90, (byte) 0x38, (byte) 0x24,
+            (byte) 0x9f, (byte) 0x8c, (byte) 0x7a, (byte) 0xce, (byte) 0x7a, (byte) 0xa5,
+            (byte) 0xb5, (byte) 0x1e, (byte) 0x74, (byte) 0x96, (byte) 0x34, (byte) 0x49,
+            (byte) 0x8b, (byte) 0xed, (byte) 0x44, (byte) 0xb3, (byte) 0xc9, (byte) 0x05,
+            (byte) 0xd7, (byte) 0x48, (byte) 0x55, (byte) 0x52, (byte) 0x59, (byte) 0x15,
+            (byte) 0x0b, (byte) 0xaa, (byte) 0x16, (byte) 0x86, (byte) 0xd2, (byte) 0x8e,
+            (byte) 0x16, (byte) 0x99, (byte) 0xe8, (byte) 0x5f, (byte) 0x11, (byte) 0x71,
+            (byte) 0x42, (byte) 0x55, (byte) 0xd1, (byte) 0xc4, (byte) 0x6f, (byte) 0x2e,
+            (byte) 0xa9, (byte) 0x64, (byte) 0x6f, (byte) 0xd8, (byte) 0xfd, (byte) 0x43,
+            (byte) 0x13, (byte) 0x24, (byte) 0xaa, (byte) 0x67, (byte) 0xe6, (byte) 0xf5,
+            (byte) 0xca, (byte) 0x80, (byte) 0x5e, (byte) 0x3a, (byte) 0x3e, (byte) 0xcc,
+            (byte) 0x4f, (byte) 0xba, (byte) 0x87, (byte) 0xe6, (byte) 0xae, (byte) 0xbf,
+            (byte) 0x8f, (byte) 0xd5, (byte) 0x28, (byte) 0x38, (byte) 0x58, (byte) 0x30,
+            (byte) 0x24, (byte) 0xf6, (byte) 0x53, (byte) 0x5b, (byte) 0x41, (byte) 0x53,
+            (byte) 0xe6, (byte) 0x45, (byte) 0xbc, (byte) 0xbe, (byte) 0xe6, (byte) 0xbb,
+            (byte) 0x5d, (byte) 0xd8, (byte) 0xa7, (byte) 0xf9, (byte) 0x64, (byte) 0x99,
+            (byte) 0x04, (byte) 0x43, (byte) 0x75, (byte) 0xd7, (byte) 0x2d, (byte) 0x32,
+            (byte) 0x0a, (byte) 0x94, (byte) 0xaf, (byte) 0x06, (byte) 0x34, (byte) 0xae,
+            (byte) 0x46, (byte) 0xbd, (byte) 0xda, (byte) 0x00, (byte) 0x0e, (byte) 0x25,
+            (byte) 0xc2, (byte) 0xf7, (byte) 0xc9, (byte) 0xc3, (byte) 0x65, (byte) 0xd2,
+            (byte) 0x08, (byte) 0x41, (byte) 0x0a, (byte) 0xf3, (byte) 0x72
+    };
+
+    /**
+     * The amount of time to allow before and after expected time for variance
+     * in timing tests.
+     */
+    private static final long SLOP_TIME_MILLIS = 15000L;
+
+    @Override
+    protected void setUp() throws Exception {
+        mAndroidKeyStore = android.security.KeyStore.getInstance();
+
+        assertTrue(mAndroidKeyStore.reset());
+
+        assertEquals(android.security.KeyStore.State.UNINITIALIZED, mAndroidKeyStore.state());
+
+        assertTrue(mAndroidKeyStore.password("1111"));
+
+        assertEquals(android.security.KeyStore.State.UNLOCKED, mAndroidKeyStore.state());
+
+        assertEquals(0, mAndroidKeyStore.saw("").length);
+
+        mKeyStore = java.security.KeyStore.getInstance(AndroidKeyStore.NAME);
+    }
+
+    private void assertAliases(final String[] expectedAliases) throws KeyStoreException {
+        final Enumeration<String> aliases = mKeyStore.aliases();
+        int count = 0;
+
+        final Set<String> expectedSet = new HashSet<String>();
+        expectedSet.addAll(Arrays.asList(expectedAliases));
+
+        while (aliases.hasMoreElements()) {
+            count++;
+            final String alias = aliases.nextElement();
+            assertTrue("The alias should be in the expected set", expectedSet.contains(alias));
+            expectedSet.remove(alias);
+        }
+        assertTrue("The expected set and actual set should be exactly equal", expectedSet.isEmpty());
+        assertEquals("There should be the correct number of keystore entries",
+                expectedAliases.length, count);
+    }
+
+    public void testKeyStore_Aliases_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertAliases(new String[] {});
+
+        assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 });
+    }
+
+    public void testKeyStore_Aliases_NotInitialized_Failure() throws Exception {
+        try {
+            mKeyStore.aliases();
+            fail("KeyStore should throw exception when not initialized");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_ContainsAliases_PrivateAndCA_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertAliases(new String[] {});
+
+        assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1));
+
+        assertTrue("Should contain generated private key", mKeyStore.containsAlias(TEST_ALIAS_1));
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        assertTrue("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_2));
+
+        assertFalse("Should not contain unadded certificate alias",
+                mKeyStore.containsAlias(TEST_ALIAS_3));
+    }
+
+    public void testKeyStore_ContainsAliases_CAOnly_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        assertTrue("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_2));
+    }
+
+    public void testKeyStore_ContainsAliases_NonExistent_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertFalse("Should contain added CA certificate", mKeyStore.containsAlias(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_DeleteEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        // TEST_ALIAS_1
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        // TEST_ALIAS_2
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        // TEST_ALIAS_3
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_3, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2, TEST_ALIAS_3 });
+
+        mKeyStore.deleteEntry(TEST_ALIAS_1);
+
+        assertAliases(new String[] { TEST_ALIAS_2, TEST_ALIAS_3 });
+
+        mKeyStore.deleteEntry(TEST_ALIAS_3);
+
+        assertAliases(new String[] { TEST_ALIAS_2 });
+
+        mKeyStore.deleteEntry(TEST_ALIAS_2);
+
+        assertAliases(new String[] { });
+    }
+
+    public void testKeyStore_DeleteEntry_EmptyStore_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        try {
+            mKeyStore.deleteEntry(TEST_ALIAS_1);
+            fail("Should throw KeyStoreException with non-existent alias");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_DeleteEntry_NonExistent_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        // TEST_ALIAS_1
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        try {
+            mKeyStore.deleteEntry(TEST_ALIAS_2);
+            fail("Should throw KeyStoreException with non-existent alias");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_GetCertificate_Single_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        assertNull("Certificate should not exist in keystore",
+                mKeyStore.getCertificate(TEST_ALIAS_2));
+
+        Certificate retrieved = mKeyStore.getCertificate(TEST_ALIAS_1);
+
+        assertNotNull("Retrieved certificate should not be null", retrieved);
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        assertEquals("Actual and retrieved certificates should be the same", actual, retrieved);
+    }
+
+    public void testKeyStore_GetCertificate_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertNull("Certificate should not exist in keystore",
+                mKeyStore.getCertificate(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_GetCertificateAlias_CAEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        assertEquals("Stored certificate alias should be found", TEST_ALIAS_1,
+                mKeyStore.getCertificateAlias(actual));
+    }
+
+    public void testKeyStore_GetCertificateAlias_PrivateKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+        assertEquals("Stored certificate alias should be found", TEST_ALIAS_1,
+                mKeyStore.getCertificateAlias(actual));
+    }
+
+    public void testKeyStore_GetCertificateAlias_CAEntry_WithPrivateKeyUsingCA_Success()
+            throws Exception {
+        mKeyStore.load(null, null);
+
+        // Insert TrustedCertificateEntry with CA name
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        // Insert PrivateKeyEntry that uses the same CA
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        assertEquals("Stored certificate alias should be found", TEST_ALIAS_2,
+                mKeyStore.getCertificateAlias(actual));
+    }
+
+    public void testKeyStore_GetCertificateAlias_NonExist_Empty_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        assertNull("Stored certificate alias should not be found",
+                mKeyStore.getCertificateAlias(actual));
+    }
+
+    public void testKeyStore_GetCertificateAlias_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory f = CertificateFactory.getInstance("X.509");
+        Certificate userCert = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+        assertNull("Stored certificate alias should be found",
+                mKeyStore.getCertificateAlias(userCert));
+    }
+
+    public void testKeyStore_GetCertificateChain_SingleLength_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        Certificate[] expected = new Certificate[2];
+        expected[0] = cf.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+        expected[1] = cf.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        Certificate[] actual = mKeyStore.getCertificateChain(TEST_ALIAS_1);
+
+        assertNotNull("Returned certificate chain should not be null", actual);
+        assertEquals("Returned certificate chain should be correct size", expected.length,
+                actual.length);
+        assertEquals("First certificate should be user certificate", expected[0], actual[0]);
+        assertEquals("Second certificate should be CA certificate", expected[1], actual[1]);
+
+        // Negative test when keystore is populated.
+        assertNull("Stored certificate alias should not be found",
+                mKeyStore.getCertificateChain(TEST_ALIAS_2));
+    }
+
+    public void testKeyStore_GetCertificateChain_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertNull("Stored certificate alias should not be found",
+                mKeyStore.getCertificateChain(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_GetCreationDate_PrivateKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        Date now = new Date();
+        Date actual = mKeyStore.getCreationDate(TEST_ALIAS_1);
+
+        Date expectedAfter = new Date(now.getTime() - SLOP_TIME_MILLIS);
+        Date expectedBefore = new Date(now.getTime() + SLOP_TIME_MILLIS);
+
+        assertTrue("Time should be close to current time", actual.before(expectedBefore));
+        assertTrue("Time should be close to current time", actual.after(expectedAfter));
+    }
+
+    public void testKeyStore_GetCreationDate_CAEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        Date now = new Date();
+        Date actual = mKeyStore.getCreationDate(TEST_ALIAS_1);
+        assertNotNull("Certificate should be found", actual);
+
+        Date expectedAfter = new Date(now.getTime() - SLOP_TIME_MILLIS);
+        Date expectedBefore = new Date(now.getTime() + SLOP_TIME_MILLIS);
+
+        assertTrue("Time should be close to current time", actual.before(expectedBefore));
+        assertTrue("Time should be close to current time", actual.after(expectedAfter));
+    }
+
+    public void testKeyStore_GetEntry_NullParams_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        Entry entry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+        assertNotNull("Entry should exist", entry);
+
+        assertTrue("Should be a PrivateKeyEntry", entry instanceof PrivateKeyEntry);
+
+        PrivateKeyEntry keyEntry = (PrivateKeyEntry) entry;
+
+        assertPrivateKeyEntryEquals(keyEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+    }
+
+    private void assertPrivateKeyEntryEquals(PrivateKeyEntry keyEntry, byte[] key, byte[] cert,
+            byte[] ca) throws Exception {
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(key));
+
+        assertEquals("Returned PrivateKey should be what we inserted", expectedKey,
+                keyEntry.getPrivateKey());
+
+        CertificateFactory certFact = CertificateFactory.getInstance("X.509");
+        Certificate expectedCert = certFact.generateCertificate(new ByteArrayInputStream(cert));
+
+        assertEquals("Returned Certificate should be what we inserted", expectedCert,
+                keyEntry.getCertificate());
+
+        Certificate[] actualChain = keyEntry.getCertificateChain();
+
+        assertEquals("First certificate in chain should be user cert", expectedCert, actualChain[0]);
+
+        if (ca == null) {
+            assertEquals("Certificate chain should not include CAs", 1, actualChain.length);
+        } else {
+            @SuppressWarnings("unchecked")
+            Collection<Certificate> expectedChain = (Collection<Certificate>) certFact
+                    .generateCertificates(new ByteArrayInputStream(ca));
+
+            int i = 1;
+            final Iterator<Certificate> it = expectedChain.iterator();
+            while (it.hasNext()) {
+                assertEquals("CA chain certificate should equal what we put in", it.next(),
+                        actualChain[i++]);
+            }
+        }
+    }
+
+    public void testKeyStore_GetEntry_Nonexistent_NullParams_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertNull("A non-existent entry should return null",
+                mKeyStore.getEntry(TEST_ALIAS_1, null));
+    }
+
+    public void testKeyStore_GetKey_NoPassword_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
+        assertNotNull("Key should exist", key);
+
+        assertTrue("Should be a RSAPrivateKey", key instanceof RSAPrivateKey);
+
+        RSAPrivateKey actualKey = (RSAPrivateKey) key;
+
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+        assertEquals("Inserted key should be same as retrieved key", actualKey, expectedKey);
+    }
+
+    public void testKeyStore_GetKey_Certificate_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertNull("Certificate entries should return null", mKeyStore.getKey(TEST_ALIAS_1, null));
+    }
+
+    public void testKeyStore_GetKey_NonExistent_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertNull("A non-existent entry should return null", mKeyStore.getKey(TEST_ALIAS_1, null));
+    }
+
+    public void testKeyStore_GetProvider_Success() throws Exception {
+        assertEquals(AndroidKeyStoreProvider.PROVIDER_NAME, mKeyStore.getProvider().getName());
+    }
+
+    public void testKeyStore_GetType_Success() throws Exception {
+        assertEquals(AndroidKeyStore.NAME, mKeyStore.getType());
+    }
+
+    public void testKeyStore_IsCertificateEntry_CA_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertTrue("Should return true for CA certificate",
+                mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsCertificateEntry_PrivateKey_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertFalse("Should return false for PrivateKeyEntry",
+                mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsCertificateEntry_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertFalse("Should return false for non-existent entry",
+                mKeyStore.isCertificateEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsKeyEntry_PrivateKey_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertTrue("Should return true for PrivateKeyEntry", mKeyStore.isKeyEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsKeyEntry_CA_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertFalse("Should return false for CA certificate", mKeyStore.isKeyEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_IsKeyEntry_NonExist_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertFalse("Should return false for non-existent entry",
+                mKeyStore.isKeyEntry(TEST_ALIAS_1));
+    }
+
+    public void testKeyStore_SetCertificate_CA_Success() throws Exception {
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+        final Certificate actual = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        mKeyStore.load(null, null);
+
+        mKeyStore.setCertificateEntry(TEST_ALIAS_1, actual);
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        Certificate retrieved = mKeyStore.getCertificate(TEST_ALIAS_1);
+
+        assertEquals("Retrieved certificate should be the same as the one inserted", actual,
+                retrieved);
+    }
+
+    public void testKeyStore_SetCertificate_CAExists_Overwrite_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+        final Certificate cert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        // TODO have separate FAKE_CA for second test
+        mKeyStore.setCertificateEntry(TEST_ALIAS_1, cert);
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+    }
+
+    public void testKeyStore_SetCertificate_PrivateKeyExists_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.importKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1,
+                FAKE_KEY_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.USER_CERTIFICATE + TEST_ALIAS_1, FAKE_USER_1));
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+        final Certificate cert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        try {
+            mKeyStore.setCertificateEntry(TEST_ALIAS_1, cert);
+            fail("Should throw when trying to overwrite a PrivateKey entry with a Certificate");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_SetEntry_PrivateKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate[] expectedChain = new Certificate[2];
+        expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+        expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+        mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+        Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+        assertNotNull("Retrieved entry should exist", actualEntry);
+
+        assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                actualEntry instanceof PrivateKeyEntry);
+
+        PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+        assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+    }
+
+    public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_PrivateKeyEntry_Success()
+            throws Exception {
+        mKeyStore.load(null, null);
+
+        final KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        // Start with PrivateKeyEntry
+        {
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+            assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+
+        // TODO make entirely new test vector for the overwrite
+        // Replace with PrivateKeyEntry
+        {
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            PrivateKeyEntry expected = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expected, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+            assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+    }
+
+    public void testKeyStore_SetEntry_CAEntry_Overwrites_PrivateKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        // Start with TrustedCertificateEntry
+        {
+            final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+                    actualEntry instanceof TrustedCertificateEntry);
+            TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+            assertEquals("Stored and retrieved certificates should be the same",
+                    expectedCertEntry.getTrustedCertificate(),
+                    actualCertEntry.getTrustedCertificate());
+        }
+
+        // Replace with PrivateKeyEntry
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+            assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+    }
+
+    public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_CAEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        // Start with PrivateKeyEntry
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = caCert;
+
+            PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+            assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+
+        // Replace with TrustedCertificateEntry
+        {
+            TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+                    actualEntry instanceof TrustedCertificateEntry);
+            TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+            assertEquals("Stored and retrieved certificates should be the same",
+                    expectedCertEntry.getTrustedCertificate(),
+                    actualCertEntry.getTrustedCertificate());
+        }
+    }
+
+    public void testKeyStore_SetEntry_PrivateKeyEntry_Overwrites_ShortPrivateKeyEntry_Success()
+            throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        // Start with PrivateKeyEntry
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] expectedChain = new Certificate[2];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            expectedChain[1] = caCert;
+
+            PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+            assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+
+        // Replace with PrivateKeyEntry that has no chain
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] expectedChain = new Certificate[1];
+            expectedChain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+            PrivateKeyEntry expectedPrivEntry = new PrivateKeyEntry(expectedKey, expectedChain);
+
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedPrivEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actualPrivEntry = (PrivateKeyEntry) actualEntry;
+            assertPrivateKeyEntryEquals(actualPrivEntry, FAKE_KEY_1, FAKE_USER_1, null);
+        }
+    }
+
+    public void testKeyStore_SetEntry_CAEntry_Overwrites_CAEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        // Insert TrustedCertificateEntry
+        {
+            final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+            TrustedCertificateEntry expectedCertEntry = new TrustedCertificateEntry(caCert);
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedCertEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+                    actualEntry instanceof TrustedCertificateEntry);
+            TrustedCertificateEntry actualCertEntry = (TrustedCertificateEntry) actualEntry;
+            assertEquals("Stored and retrieved certificates should be the same",
+                    expectedCertEntry.getTrustedCertificate(),
+                    actualCertEntry.getTrustedCertificate());
+        }
+
+        // Replace with TrustedCertificateEntry of USER
+        {
+            final Certificate userCert = f
+                    .generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+
+            TrustedCertificateEntry expectedUserEntry = new TrustedCertificateEntry(userCert);
+            mKeyStore.setEntry(TEST_ALIAS_1, expectedUserEntry, null);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+            assertTrue("Retrieved entry should be of type TrustedCertificateEntry",
+                    actualEntry instanceof TrustedCertificateEntry);
+            TrustedCertificateEntry actualUserEntry = (TrustedCertificateEntry) actualEntry;
+            assertEquals("Stored and retrieved certificates should be the same",
+                    expectedUserEntry.getTrustedCertificate(),
+                    actualUserEntry.getTrustedCertificate());
+        }
+    }
+
+    public void testKeyStore_SetKeyEntry_ProtectedKey_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+        final Certificate[] chain = new Certificate[2];
+        chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+        chain[1] = caCert;
+
+        try {
+            mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, "foo".toCharArray(), chain);
+            fail("Should fail when a password is specified");
+        } catch (KeyStoreException success) {
+        }
+    }
+
+    public void testKeyStore_SetKeyEntry_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        KeyFactory keyFact = KeyFactory.getInstance("RSA");
+        PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+        final Certificate[] chain = new Certificate[2];
+        chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+        chain[1] = caCert;
+
+        mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+        Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+        assertNotNull("Retrieved entry should exist", actualEntry);
+
+        assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                actualEntry instanceof PrivateKeyEntry);
+
+        PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+        assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+    }
+
+    public void testKeyStore_SetKeyEntry_Replaced_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        final CertificateFactory f = CertificateFactory.getInstance("X.509");
+
+        final Certificate caCert = f.generateCertificate(new ByteArrayInputStream(FAKE_CA_1));
+
+        // Insert initial key
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] chain = new Certificate[2];
+            chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            chain[1] = caCert;
+
+            mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+            assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+
+        // TODO make a separate key
+        // Replace key
+        {
+            KeyFactory keyFact = KeyFactory.getInstance("RSA");
+            PrivateKey privKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_KEY_1));
+            final Certificate[] chain = new Certificate[2];
+            chain[0] = f.generateCertificate(new ByteArrayInputStream(FAKE_USER_1));
+            chain[1] = caCert;
+
+            mKeyStore.setKeyEntry(TEST_ALIAS_1, privKey, null, chain);
+
+            Entry actualEntry = mKeyStore.getEntry(TEST_ALIAS_1, null);
+            assertNotNull("Retrieved entry should exist", actualEntry);
+
+            assertTrue("Retrieved entry should be of type PrivateKeyEntry",
+                    actualEntry instanceof PrivateKeyEntry);
+
+            PrivateKeyEntry actual = (PrivateKeyEntry) actualEntry;
+
+            assertPrivateKeyEntryEquals(actual, FAKE_KEY_1, FAKE_USER_1, FAKE_CA_1);
+        }
+    }
+
+    public void testKeyStore_Size_Success() throws Exception {
+        mKeyStore.load(null, null);
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_1, FAKE_CA_1));
+
+        assertEquals("The keystore size should match expected", 1, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_1 });
+
+        assertTrue(mAndroidKeyStore.put(Credentials.CA_CERTIFICATE + TEST_ALIAS_2, FAKE_CA_1));
+
+        assertEquals("The keystore size should match expected", 2, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 });
+
+        assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
+
+        assertEquals("The keystore size should match expected", 3, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2, TEST_ALIAS_3 });
+
+        assertTrue(mAndroidKeyStore.delete(Credentials.CA_CERTIFICATE + TEST_ALIAS_1));
+
+        assertEquals("The keystore size should match expected", 2, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_2, TEST_ALIAS_3 });
+
+        assertTrue(mAndroidKeyStore.delKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
+
+        assertEquals("The keystore size should match expected", 1, mKeyStore.size());
+        assertAliases(new String[] { TEST_ALIAS_2 });
+    }
+
+    public void testKeyStore_Store_LoadStoreParam_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        try {
+            mKeyStore.store(null);
+            fail("Should throw UnsupportedOperationException when trying to store");
+        } catch (UnsupportedOperationException success) {
+        }
+    }
+
+    public void testKeyStore_Load_InputStreamSupplied_Failure() throws Exception {
+        byte[] buf = "FAKE KEYSTORE".getBytes();
+        ByteArrayInputStream is = new ByteArrayInputStream(buf);
+
+        try {
+            mKeyStore.load(is, null);
+            fail("Should throw IllegalArgumentException when InputStream is supplied");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testKeyStore_Load_PasswordSupplied_Failure() throws Exception {
+        try {
+            mKeyStore.load(null, "password".toCharArray());
+            fail("Should throw IllegalArgumentException when password is supplied");
+        } catch (IllegalArgumentException success) {
+        }
+    }
+
+    public void testKeyStore_Store_OutputStream_Failure() throws Exception {
+        mKeyStore.load(null, null);
+
+        OutputStream sink = new ByteArrayOutputStream();
+        try {
+            mKeyStore.store(sink, null);
+            fail("Should throw UnsupportedOperationException when trying to store");
+        } catch (UnsupportedOperationException success) {
+        }
+
+        try {
+            mKeyStore.store(sink, "blah".toCharArray());
+            fail("Should throw UnsupportedOperationException when trying to store");
+        } catch (UnsupportedOperationException success) {
+        }
+    }
+}
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 9f35b8d..07a2d7b 100755
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -19,9 +19,11 @@
 import android.app.Activity;
 import android.security.KeyStore;
 import android.test.ActivityUnitTestCase;
+import android.test.AssertionFailedError;
 import android.test.suitebuilder.annotation.MediumTest;
 import java.nio.charset.Charsets;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.HashSet;
 
 /**
@@ -403,4 +405,52 @@
         assertFalse("Should fail to ungrant key to other user second time",
                 mKeyStore.ungrant(TEST_KEYNAME, 0));
     }
+
+    /**
+     * The amount of time to allow before and after expected time for variance
+     * in timing tests.
+     */
+    private static final long SLOP_TIME_MILLIS = 15000L;
+
+    public void testGetmtime_Success() throws Exception {
+        assertTrue("Password should work for keystore",
+                mKeyStore.password(TEST_PASSWD));
+
+        assertTrue("Should be able to import key when unlocked",
+                mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+
+        long now = System.currentTimeMillis();
+        long actual = mKeyStore.getmtime(TEST_KEYNAME);
+
+        long expectedAfter = now - SLOP_TIME_MILLIS;
+        long expectedBefore = now + SLOP_TIME_MILLIS;
+
+        assertLessThan("Time should be close to current time", expectedBefore, actual);
+        assertGreaterThan("Time should be close to current time", expectedAfter, actual);
+    }
+
+    private static void assertLessThan(String explanation, long expectedBefore, long actual) {
+        if (actual >= expectedBefore) {
+            throw new AssertionFailedError(explanation + ": actual=" + actual
+                    + ", expected before: " + expectedBefore);
+        }
+    }
+
+    private static void assertGreaterThan(String explanation, long expectedAfter, long actual) {
+        if (actual <= expectedAfter) {
+            throw new AssertionFailedError(explanation + ": actual=" + actual
+                    + ", expected after: " + expectedAfter);
+        }
+    }
+
+    public void testGetmtime_NonExist_Failure() throws Exception {
+        assertTrue("Password should work for keystore",
+                mKeyStore.password(TEST_PASSWD));
+
+        assertTrue("Should be able to import key when unlocked",
+                mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+
+        assertEquals("-1 should be returned for non-existent key",
+                -1L, mKeyStore.getmtime(TEST_KEYNAME2));
+    }
 }
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index caeeb87..27e198c 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -148,8 +148,8 @@
                 cacheBlock->mX += roundedUpW;
                 if (mHeight - glyphH >= glyphH) {
                     // There's enough height left over to create a new CacheBlock
-                    CacheBlock *newBlock = new CacheBlock(oldX, glyphH, roundedUpW,
-                            mHeight - glyphH);
+                    CacheBlock *newBlock = new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE,
+                            roundedUpW, mHeight - glyphH - TEXTURE_BORDER_SIZE);
 #if DEBUG_FONT_RENDERER
                     ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
                             newBlock, newBlock->mX, newBlock->mY,
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
index 4e0e0f2..4982a47 100755
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ b/media/jni/mediaeditor/VideoEditorClasses.cpp
@@ -1853,6 +1853,9 @@
                             // Get the clip settings.
                             videoEditClasses_getClipSettings(pResult, pEnv, clipSettings,
                                 &pSettings->pClipList[i]);
+
+                            // Free the local references to avoid memory leaks
+                            pEnv->DeleteLocalRef(clipSettings);
                         }
                     }
                 }
@@ -1877,6 +1880,9 @@
                             // Get the transition settings.
                             videoEditClasses_getTransitionSettings(pResult, pEnv,
                                     transitionSettings, &pSettings->pTransitionList[i]);
+
+                            // Free the local references to avoid memory leaks
+                            pEnv->DeleteLocalRef(transitionSettings);
                         }
                     }
                 }
@@ -1900,6 +1906,9 @@
                             // Get the effect settings.
                             videoEditClasses_getEffectSettings(pResult, pEnv, effectSettings,
                                     &pSettings->Effects[i]);
+
+                            // Free the local references to avoid memory leaks
+                            pEnv->DeleteLocalRef(effectSettings);
                         }
                     }
                 }
diff --git a/media/jni/mediaeditor/VideoEditorJava.cpp b/media/jni/mediaeditor/VideoEditorJava.cpp
index ec8050f..bcf90990 100755
--- a/media/jni/mediaeditor/VideoEditorJava.cpp
+++ b/media/jni/mediaeditor/VideoEditorJava.cpp
@@ -387,6 +387,9 @@
                 (*pLength) = length;
             }
         }
+
+        // Delete local references to avoid memory leaks
+        pEnv->DeleteLocalRef(string);
     }
 
     // Return the string.
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 41ec120..41c28c0 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -380,6 +380,9 @@
                     pEnv->GetIntField(object,fid);
    M4OSA_TRACE1_1("videoRotation = %d",
                     pSettings->ClipProperties.videoRotationDegrees);
+
+   // Free the local references to avoid memory leaks
+   pEnv->DeleteLocalRef(clazz);
 }
 
 static void jniPreviewProgressCallback (void* cookie, M4OSA_UInt32 msgType,
@@ -1849,7 +1852,9 @@
                 "not initialized");
             if (needToBeLoaded) {
                 getClipSetting(pEnv,properties, pContext->pEditSettings->pClipList[i]);
+                pEnv->DeleteLocalRef(properties);
             } else {
+                pEnv->DeleteLocalRef(properties);
                 goto videoEditor_populateSettings_cleanup;
             }
         }
diff --git a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
index 436e579..f11b499 100644
--- a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
+++ b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
@@ -119,7 +119,7 @@
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
-        if (ActivityManager.isHighEndGfx(display)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
         lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e13378f..2eee31d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -132,6 +132,14 @@
             android:excludeFromRecents="true">
         </activity>
 
+        <!-- started from UsbDebuggingManager -->
+        <activity android:name=".usb.UsbDebuggingActivity"
+            android:permission="android.permission.MANAGE_USB"
+            android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+            android:finishOnCloseSystemDialogs="true"
+            android:excludeFromRecents="true">
+        </activity>
+
         <!-- started from NetworkPolicyManagerService -->
         <activity
             android:name=".net.NetworkOverLimitActivity"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 2db520a..b63ed4a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Sien"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gebruik by verstek vir hierdie USB-toestel"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gebruik by verstek vir hierdie USB-toebehoorsel"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoem om skerm te vul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strek om skerm te vul"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Versoenbaarheidszoem"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 93547c1..0d41cc7 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"ዕይታ"</string>
     <string name="always_use_device" msgid="1450287437017315906">"ለዚህ USB  መሣሪያ በነባሪነት ተጠቀም"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"ለዚህ USB  ተቀጥላ በነባሪነት ተጠቀም"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"የUSB ማረሚያ ይፈቀድ?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"የUSB ማረም ከዚህ ኮምፒውተር ይፈቀድ?"\n"የእርስዎ RSA ቁልፍ ጣት አሻራ "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g> ነው"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"ለዚህ ኮምፒውተር ሁልጊዜ ፍቀድ"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ማያ እንዲሞላ አጉላ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ማያ ለመሙለት ሳብ"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"የተኳኋኝነት አጉላ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 9b975fe..d3d4c7f 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"عرض"</string>
     <string name="always_use_device" msgid="1450287437017315906">"الاستخدام بشكل افتراضي لجهاز USB هذا"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"الاستخدام بشكل افتراضي لملحق USB هذا"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"تكبير/تصغير لملء الشاشة"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"توسيع بملء الشاشة"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"تكبير/تصغير التوافق"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index a8a17f0..8216e2b 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Прагляд"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Выкарыстоўваць налады па змаўчанні для дадзенай USB-прылады"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Дазволіць адладку USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Дазволіць USB-адладку з гэтага камп\'ютара?"\n"Ваш адбiтак ключа RSA"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Дазваляць гэтаму камп\'ютару"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Павял. на ўвесь экран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Расцягн. на ўвесь экран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Маштабаванне для сумяшчальнасцi"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 0270678..ba57e91 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Преглед"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Използване по подразб. за това USB устройство"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Използване по подразб. за този аксесоар за USB"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Мащаб – запълва екрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Промяна на мащаба за съвместимост"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 2e48570..3eb078d 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Mostra"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilitza de manera predet. per al dispositiu USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Vols permetre la depuració USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vols permetre la depuració USB des d\'aquest equip?"\n"L\'empremta de la teva clau RSA és"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Dóna sempre permís a aquest equip"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitat"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c9b6a522..fb6584e 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Zobrazit"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pro toto zařízení USB použít jako výchozí"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pro toto periferní zařízení USB použít jako výchozí"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava velikosti z důvodu kompatibility"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 370865c..48cab36 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Vis"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Brug som standard til denne USB-enhed"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Brug som standard til dette USB-tilbehør"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Vil du tillade USB-fejlretning?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vil du tillade USB-fejlretning fra denne computer?"\n"Dit fingeraftryk for RSA-nøglen er"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Tillad altid denne computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom til fuld skærm"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stræk til fuld skærm"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitetszoom"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 65c870f..4bcbc31 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Anzeigen"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Standardmäßig für dieses USB-Gerät verwenden"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Standardmäßig für dieses USB-Zubehör verwenden"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"USB-Debugging zulassen?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"USB-Debugging auf diesem Computer zulassen?"\n"Ihr Fingerabdruck des RSA-Schlüssels lautet"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>."</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Auf diesem Computer immer zulassen"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom auf Bildschirmgröße"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitätszoom"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6e147e2..2231a8c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Προβολή"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Χρήση από προεπιλογή για αυτή τη συσκευή USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Χρήση από προεπιλογή για αυτό το εξάρτημα USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Να επιτρέπεται ο εντοπισμός σφαλμάτων USB;"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Να επιτρέπεται ο εντοπισμός σφαλμάτων USB από αυτόν τον υπολογιστή;"\n"Το αποτύπωμα κλειδιού σας RSA είναι"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Να επιτρέπεται πάντα σε αυτόν τον υπολογιστή"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Ζουμ σε πλήρη οθόνη"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Προβoλή σε πλήρη οθ."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Ζουμ για συμβατότητα"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index afabd34..671ac1b 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"View"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Use by default for this USB device"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Use by default for this USB accessory"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Allow USB Debugging?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Allow USB Debugging from this computer?"\n"Your RSA key fingerprint is"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Always allow this computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibility zoom"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index b83aad5..4c07d9f 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Se usa de forma predeterminada para este dispositivo USB."</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Se usa de forma predeterminada para este accesorio USB."</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ocupar la pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index c0cab22..cd03d92 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar de forma predeterminada para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar de forma predeterminada para este accesorio USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"¿Permitir depuración USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"¿Quieres permitir la depuración USB en este ordenador?"\n"La huella digital de tu clave RSA es:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Permitir siempre en este ordenador"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ajustar"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Expandir para ajustar"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidad"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 8adf8ed..17484377 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Kuva"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Kasuta vaikimisi selle USB-seadme jaoks"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Vaikimisi kasuta seda USB-lisaseadet"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Suumi ekraani täitmiseks"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venita ekraani täitmiseks"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Sobivussuum"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 2c66897..e75d5f0 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"مشاهده"</string>
     <string name="always_use_device" msgid="1450287437017315906">"استفاده به صورت پیش‌فرض برای این دستگاه USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"استفاده به صورت پیش‌فرض برای این دستگاه USB"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"بزرگنمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"بزرگنمایی سازگاری"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index bec1b48..5132502 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Näytä"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Käytä oletuksena tällä USB-laitteella"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Käytä oletuksena tällä USB-lisälaitteella"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Sallitaanko USB-vianetsintä?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Sallitaanko USB-vianetsintä tällä tietokoneella?"\n"RSA-avaimesi sormenjälki on"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Salli vianetsintä tällä tietokoneella aina"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomaa koko näyttöön"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Yhteensopivuuszoomaus"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 15489f5a..d862df8 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Afficher"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utiliser par défaut pour ce périphérique USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliser par défaut pour cet accessoire USB"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilité"</string>
@@ -135,7 +141,7 @@
     <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Données désactivées"</string>
     <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Vous avez atteint le plafond de consommation de données spécifié."\n\n"Si vous utilisez des données supplémentaires, celles-ci pourront être facturées par l\'opérateur."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Réactiver connexion données"</string>
-    <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion"</string>
+    <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c66b680..b45b4ce 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"देखें"</string>
     <string name="always_use_device" msgid="1450287437017315906">"इस USB उपकरण के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"इस USB एसेसरी के लिए डिफ़ॉल्‍ट रूप से उपयोग करें"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"स्‍क्रीन भरने हेतु ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्‍क्रीन को भरने के लिए खींचें"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"संगतता ज़ूम"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 1a10ecb..620e193 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Koristi se prema zadanim postavkama za ovaj USB uređaj"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Koristi se prema zadanim postavkama za ovaj USB pribor"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj i ispuni zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilno zumiranje"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 25f3e54..1805ce0 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Megtekintés"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Alapértelmezett használat ehhez az USB-eszközhöz"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Alapértelmezett használat ehhez az USB-kiegészítőhöz"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Nagyítás a kitöltéshez"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitás -- nagyítás/kicsinyítés"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 3ad4fd1..65e47dd 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara default untuk perangkat USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara default untuk aksesori USB ini"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Izinkan Debugging USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Izinkan Debugging USB dari komputer ini?"\n"Sidik jari kunci RSA Anda adalah"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Selalu izinkan komputer ini"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Perbesar utk mengisi layar"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rentangkn utk mngisi layar"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Perbesar/perkecil untuk kompatibilitas"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index df7f188..49b0fb0 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizza"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usa per impostazione predef. per dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usa per impostazione predef. per accessorio USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Consentire debug USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Consentire il debug USB da questo computer? "\n"La fingerprint della tua chiave RSA è "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Consenti sempre da questo computer"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per riempire schermo"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estendi per riemp. schermo"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom compatibilità"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 2e75e72..59730af 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"הצג"</string>
     <string name="always_use_device" msgid="1450287437017315906">"השתמש כברירת מחדל עבור מכשיר USB זה"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"השתמש כברירת מחדל עבור אביזר USB זה"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"האם לאפשר ניקוי באגים ב-USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"האם להרשות ניקוי באגים ב-USB ממחשב זה?"\n"טביעת האצבע של מפתח ה-RSA שלך היא"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"הרשה תמיד במחשב זה"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"הגדל תצוגה כדי למלא את המסך"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"מתח כדי למלא את המסך"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"שינוי מרחק מתצוגה לצורך תאימות"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 2d73518..8eda13f 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"表示"</string>
     <string name="always_use_device" msgid="1450287437017315906">"このUSBデバイスにデフォルトで使用する"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"このUSBアクセサリにデフォルトで使用する"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"互換ズーム"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 438734e..9562237c 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"보기"</string>
     <string name="always_use_device" msgid="1450287437017315906">"이 USB 기기에 기본값으로 사용"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"이 USB 액세서리에 기본값으로 사용"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"전체화면 모드로 확대"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"호환성 확대/축소"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 62c6a06..daacca55 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Žiūrėti"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Šiam USB įreng. naudoti pagal numat. nustatymus"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Šiam USB priedui naudoti pagal numat. nustatymus"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Keisti mast., kad atit. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Suderinamumo mastelio keitimas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 5929240..b189fd2 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Skatīt"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pēc noklusējuma izmantot šai USB ierīcei"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pēc noklusējuma izmantot šim USB piederumam"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Tālumm., lai aizp. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Saderības tālummaiņa"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 5bf9811..8da9ed5 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara lalai untuk peranti USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara lalai untuk aksesori USB ini"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zum keserasian"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9a0b2de..e7005fa 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Vis"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bruk som standard for denne USB-enheten"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bruk som standard for dette USB-tilbehøret"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Vil du tillate USB-feilsøking?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vil du tillate USB-feilsøking fra denne datamaskinen?"\n"Nøkkelfingeravtrykket ditt for RSA er"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Gi alltid tillatelse til denne datamaskinen"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom for å fylle skjermen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kompatibilitets-zooming"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 33bab76b..d5e8444 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Weergeven"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Standaard gebruiken voor dit USB-apparaat"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Standaard gebruiken voor dit USB-accessoire"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"USB-foutopsporing toestaan?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"USB-foutopsporing toestaan vanaf deze computer?"\n"Uw RSA-sleutelvingerafdruk is"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Deze computer altijd toestaan"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom om scherm te vullen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rek uit v. schermvulling"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibiliteitszoom"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 6a7639f..50d5e3b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Wyświetl"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Używaj domyślnie dla tego urządzenia USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Używaj domyślnie dla tego akcesorium USB"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Powiększ, aby wypełnić ekran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Powiększenie w trybie zgodności"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 655c46e..b583aea 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizar por predefinição para este aparelho USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilizar por predefinição para este acessório USB"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para preencher o ecrã"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Esticar p. caber em ec. int."</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilidade"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 5fabdfd..bae61d0 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizar"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar por padrão para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar por padrão para este acessório USB"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom em modo de compatibilidade"</string>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index e0c0886..ea88ddd 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -86,6 +86,12 @@
     <skip />
     <!-- no translation found for always_use_accessory (1210954576979621596) -->
     <skip />
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <!-- no translation found for compat_mode_on (6623839244840638213) -->
     <skip />
     <!-- no translation found for compat_mode_off (4434467572461327898) -->
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 58a9a9b..5580f01 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilitate"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 155238a..567d1de 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -25,7 +25,7 @@
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показать уведомления"</string>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Удаление из списка"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"О приложении"</string>
-    <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Нет данных"</string>
+    <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"В последнее время вы не запускали приложения."</string>
     <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Закрыть недавние приложения"</string>
   <plurals name="status_bar_accessibility_recent_apps">
     <item quantity="one" msgid="5854176083865845541">"Недавних приложений: 1"</item>
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Просмотр"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Использовать по умолчанию для этого USB-устройства"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Использовать по умолчанию для этого USB-аксессуара"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Подогнать по размерам экрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Масштаб и совместимость"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 0c15f6c..01a8606 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Zobraziť"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pre toto zariadenie USB použiť ako predvolené"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pre toto periférne zar. USB použiť ako predvolené"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Úprava veľkosti z dôvodu kompatibility"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 2b385fc..1bed89b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Privzeto uporabi za to napravo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Privzeto uporabi za ta dodatek USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Ali dovolite odpravljanje težav s povezavo USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Ali dovolite odpravljanje težav s povezavo USB v tem računalniku?"\n"Prstni odtis ključa RSA je"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Vedno dovoli za ta računalnik"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Povečava čez cel zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Razširitev združljivosti"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index c43b66f..3987d76 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Прикажи"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Користи подразумевано за овај USB уређај"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Користи подразумевано за овај USB додатак"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај на целом екрану"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Компатибилно зумирање"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e3a1481..f09dc2a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Visa"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Använd som standard för den här USB-enheten"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Använd som standard för det här USB-tillbehöret"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Ska USB-felsökning tillåtas?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Vill du tillåta USB-felsökning från den här datorn?"\n"Din RSA-fingeravtrycksnyckel är"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Tillåt alltid för den här datorn"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zooma för att fylla skärm"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Dra för att fylla skärmen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom i kompatibilitetsläge"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index b333bbe..a6fec13 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -56,6 +56,9 @@
     <string name="label_view" msgid="6304565553218192990">"Ona"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Kwa kifaa hiki cha USB tumia chaguo-msingi"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Tumia kama chaguo-msingi ya kifuasi hiki cha USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Ruhusu Utatuaji USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Ruhusu Utatuaji wa USB kutoka kwenye kompyuta hii?"\n"Kitufe chako RSA cha alama ya kidole ni "\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Kila wakati ruhusu kompyuta hii"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Kuza ili kujaza skrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Tanua ili kujaza skrini"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Kukuza kwa Utangamanifu"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 4d46a5d..0c42f87 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"ดู"</string>
     <string name="always_use_device" msgid="1450287437017315906">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์ USB นี้"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์เสริม USB นี้"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"ความเข้ากันได้ของการย่อ/ขยาย"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index a93e511..bb0a2bf 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Tingnan"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gamitin bilang default para sa USB device"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gamitin bilang default sa USB accessory na ito"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"I-zoom upang punan screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom sa pagiging Tugma"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 0f6af69..6c30abe 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Görüntüle"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bu USB cihazı için varsayılan olarak kullan"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bu USB aksesuar için varsayılan olarak kullan"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Yakınlaştır (ekranı kaplasın)"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Uyumluluk yakınlaştırması"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 5922e24..973c6bc 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -58,6 +58,9 @@
     <string name="label_view" msgid="6304565553218192990">"Переглянути"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Використовувати за умовчанням для пристрою USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Використовувати за умовчанням для аксесуара USB"</string>
+    <string name="usb_debugging_title" msgid="1114766024068112429">"Дозволити налагодження USB?"</string>
+    <string name="usb_debugging_message" msgid="719863946976291180">"Дозволити налагодження USB на цьому комп’ютері?"\n"Цифровий відбиток вашого ключа RSA:"\n"<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_always" msgid="4253099426793114693">"Завжди дозволяти цьому комп’ютеру"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Масштабув. на весь екран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Розтягнути на весь екран"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Масштабування для сумісності"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 15141c9..cef38ecb 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Xem"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sử dụng theo mặc định cho thiết bị USB này"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sử dụng theo mặc định cho phụ kiện USB này"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"T.phóng để lấp đầy m.hình"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Thu phóng tương thích"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 19470e6..d0f4a9c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该 USB 设备"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"默认情况下用于该 USB 配件"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"兼容性缩放"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index fa2e9d1..2e5211f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"預設用於這個 USB 裝置"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"預設用於這個 USB 配件"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"相容性縮放"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 1e11f04..07c9f0f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -58,6 +58,12 @@
     <string name="label_view" msgid="6304565553218192990">"Buka"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sebenzisa ngokuzenzakalelayo yale divayisi ye-USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sebenzisa ngokuzenzakalelayo kule-accessory ye-USB"</string>
+    <!-- no translation found for usb_debugging_title (1114766024068112429) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (719863946976291180) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (4253099426793114693) -->
+    <skip />
     <string name="compat_mode_on" msgid="6623839244840638213">"Sondeza ukugcwalisa isikrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nweba ukugcwalisa isikrini"</string>
     <string name="compat_mode_help_header" msgid="7969493989397529910">"Ukuhambelana Kokusondeza"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2ce950f..5747f22 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -154,6 +154,15 @@
     <!-- Checkbox label for USB accessory dialogs.  [CHAR LIMIT=50] -->
     <string name="always_use_accessory">Use by default for this USB accessory</string>
 
+    <!-- Title of confirmation dialog for USB debugging -->
+    <string name="usb_debugging_title">Allow USB Debugging?</string>
+
+    <!-- Message of confirmation dialog for USB debugging -->
+    <string name="usb_debugging_message">Allow USB Debugging from this computer?\nYour RSA key fingerprint is\n<xliff:g id="fingerprint">%1$s</xliff:g></string>
+
+    <!-- Option to always allow USB debugging from the attached computer -->
+    <string name="usb_debugging_always">Always allow this computer</string>
+
     <!-- Checkbox label for application compatibility mode ON (zooming app to look like it's running
          on a phone).  [CHAR LIMIT=25] -->
     <string name="compat_mode_on">Zoom to fill screen</string>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index a72074e..2512c02 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -74,10 +74,7 @@
         //noinspection PointlessBooleanExpression,ConstantConditions
         if (FIXED_SIZED_SURFACE && USE_OPENGL) {
             if (!isEmulator()) {
-                WindowManager windowManager =
-                        (WindowManager) getSystemService(Context.WINDOW_SERVICE);
-                Display display = windowManager.getDefaultDisplay();
-                mIsHwAccelerated = ActivityManager.isHighEndGfx(display);
+                mIsHwAccelerated = ActivityManager.isHighEndGfx();
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 0a57499..1bde949 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -31,6 +31,7 @@
 import android.os.ServiceManager;
 import android.util.Slog;
 import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
 
 public class SystemUIService extends Service {
     static final String TAG = "SystemUIService";
@@ -67,8 +68,7 @@
     @Override
     public void onCreate() {
         // Pick status bar or system bar.
-        IWindowManager wm = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
+        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
         try {
             SERVICES[0] = wm.hasSystemNavBar()
                     ? R.string.config_systemBarComponent
diff --git a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
index 4852a3e..7628754 100644
--- a/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
+++ b/packages/SystemUI/src/com/android/systemui/UniverseBackground.java
@@ -33,6 +33,7 @@
 import android.view.View;
 import android.view.ViewRootImpl;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.view.animation.Transformation;
 import android.widget.FrameLayout;
 
@@ -96,7 +97,7 @@
     public UniverseBackground(Context context) {
         super(context);
         setBackgroundColor(0xff000000);
-        mSession = ViewRootImpl.getWindowSession(context.getMainLooper());
+        mSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
         mContent = View.inflate(context, R.layout.universe, null);
         addView(mContent);
         mContent.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
@@ -155,7 +156,7 @@
         }
     }
 
-    public WindowManager.LayoutParams getLayoutParams(Display display) {
+    public WindowManager.LayoutParams getLayoutParams() {
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND,
@@ -165,7 +166,7 @@
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.OPAQUE);
         // this will allow the window to run in an overlay on devices that support this
-        if (ActivityManager.isHighEndGfx(display)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
         lp.setTitle("UniverseBackground");
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index d5a76bc..b407078 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -49,6 +49,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AnimationUtils;
 import android.widget.AdapterView;
@@ -488,9 +489,7 @@
         mChoreo = new Choreographer(this, mRecentsScrim, mRecentsContainer, mRecentsNoApps, this);
 
         if (mRecentsScrim != null) {
-            Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
-            mHighEndGfx = ActivityManager.isHighEndGfx(d);
+            mHighEndGfx = ActivityManager.isHighEndGfx();
             if (!mHighEndGfx) {
                 mRecentsScrim.setBackground(null);
             } else if (mRecentsScrim.getBackground() instanceof BitmapDrawable) {
@@ -733,8 +732,7 @@
         if (mTransitionBg == null) {
             mTransitionBg = (View) findViewById(R.id.recents_transition_background);
 
-            IWindowManager wm = IWindowManager.Stub.asInterface(
-                    ServiceManager.getService(Context.WINDOW_SERVICE));
+            IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
             try {
                 if (!wm.hasSystemNavBar()) {
                     FrameLayout.LayoutParams lp =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 646f98a..e9e043e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -61,9 +61,9 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.PopupMenu;
@@ -127,18 +127,12 @@
      */
     protected abstract void createAndAddWindows();
 
+    protected WindowManager mWindowManager;
+    protected IWindowManager mWindowManagerService;
     protected Display mDisplay;
-    private IWindowManager mWindowManager;
+
     private boolean mDeviceProvisioned = false;
 
-    public IWindowManager getWindowManager() {
-        return mWindowManager;
-    }
-
-    public Display getDisplay() {
-        return mDisplay;
-    }
-
     public IStatusBarService getStatusBarService() {
         return mBarService;
     }
@@ -189,17 +183,15 @@
     };
 
     public void start() {
-        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
+        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
+        mDisplay = mWindowManager.getDefaultDisplay();
 
         mProvisioningObserver.onChange(false); // set up
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED), true,
                 mProvisioningObserver);
 
-        mWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
-
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
 
@@ -436,7 +428,7 @@
         boolean firstScreenful = false;
         if (mRecentsPanel != null) {
             visible = mRecentsPanel.isShowing();
-            WindowManagerImpl.getDefault().removeView(mRecentsPanel);
+            mWindowManager.removeView(mRecentsPanel);
             if (visible) {
                 recentTasksList = mRecentsPanel.getRecentTasksList();
                 firstScreenful = mRecentsPanel.getFirstScreenful();
@@ -456,7 +448,7 @@
 
         WindowManager.LayoutParams lp = getRecentsLayoutParams(mRecentsPanel.getLayoutParams());
 
-        WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
+        mWindowManager.addView(mRecentsPanel, lp);
         mRecentsPanel.setBar(this);
         if (visible) {
             mRecentsPanel.show(true, false, recentTasksList, firstScreenful);
@@ -469,7 +461,7 @@
         boolean visible = false;
         if (mSearchPanelView != null) {
             visible = mSearchPanelView.isShowing();
-            WindowManagerImpl.getDefault().removeView(mSearchPanelView);
+            mWindowManager.removeView(mSearchPanelView);
         }
 
         // Provide SearchPanel with a temporary parent to allow layout params to work.
@@ -482,7 +474,7 @@
 
         WindowManager.LayoutParams lp = getSearchLayoutParams(mSearchPanelView.getLayoutParams());
 
-        WindowManagerImpl.getDefault().addView(mSearchPanelView, lp);
+        mWindowManager.addView(mSearchPanelView, lp);
         mSearchPanelView.setBar(this);
         if (visible) {
             mSearchPanelView.show(true, false);
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 63c9b79..33973b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -18,13 +18,11 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Message;
@@ -34,19 +32,14 @@
 import android.view.animation.AccelerateInterpolator;
 import android.view.Display;
 import android.view.MotionEvent;
-import android.view.VelocityTracker;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.Surface;
-import android.view.Window;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.StringBuilder;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
@@ -244,7 +237,8 @@
             } else {
                 return;
             }
-            WindowManagerImpl.getDefault().updateViewLayout(this, lp);
+            WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
+            wm.updateViewLayout(this, lp);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index b595257..33f467f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -66,6 +66,7 @@
     private final Runnable mStopAnimator = new Runnable() { public void run() {
         if (mTimeAnimator.isStarted()) {
             mTimeAnimator.end();
+            mRubberbanding = false;
         }
     }};
 
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 49e4760..2886441 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -60,9 +60,9 @@
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -150,7 +150,6 @@
     int mIconHPadding = -1;
     Display mDisplay;
 
-    IWindowManager mWindowManager;
     IDreamManager mDreamManager;
 
     StatusBarWindowView mStatusBarWindow;
@@ -261,9 +260,6 @@
         mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                 .getDefaultDisplay();
 
-        mWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
-
         mDreamManager = IDreamManager.Stub.asInterface(
                 ServiceManager.checkService("dreams"));
 
@@ -332,7 +328,7 @@
         mSettingsPanel = (PanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
         mSettingsPanel.setOnTouchListener(clickStopper);
 
-        if (!ActivityManager.isHighEndGfx(mDisplay)) {
+        if (!ActivityManager.isHighEndGfx()) {
             mStatusBarWindow.setBackground(null);
             mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
                     R.color.notification_panel_solid_background)));
@@ -352,7 +348,7 @@
         updateShowSearchHoldoff();
 
         try {
-            boolean showNav = mWindowManager.hasNavigationBar();
+            boolean showNav = mWindowManagerService.hasNavigationBar();
             if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav);
             if (showNav) {
                 mNavigationBarView =
@@ -474,7 +470,7 @@
                 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         } else {
             lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
@@ -499,7 +495,7 @@
                 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
         lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
@@ -535,7 +531,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
         lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+        mWindowManager.updateViewLayout(mNavigationBarView, lp);
     }
 
     @Override
@@ -544,7 +540,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
         lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
+        mWindowManager.updateViewLayout(mNavigationBarView, lp);
     }
 
     protected int getStatusBarGravity() {
@@ -620,8 +616,7 @@
 
         prepareNavigationBarView();
 
-        WindowManagerImpl.getDefault().addView(
-                mNavigationBarView, getNavigationBarLayoutParams());
+        mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     private void repositionNavigationBar() {
@@ -629,8 +624,7 @@
 
         prepareNavigationBarView();
 
-        WindowManagerImpl.getDefault().updateViewLayout(
-                mNavigationBarView, getNavigationBarLayoutParams());
+        mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     private WindowManager.LayoutParams getNavigationBarLayoutParams() {
@@ -644,7 +638,7 @@
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.OPAQUE);
         // this will allow the navbar to run in an overlay on devices that support this
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         }
 
@@ -671,7 +665,7 @@
         lp.packageName = mContext.getPackageName();
         lp.windowAnimations = R.style.Animation_StatusBar_IntruderAlert;
 
-        WindowManagerImpl.getDefault().addView(mIntruderAlertView, lp);
+        mWindowManager.addView(mIntruderAlertView, lp);
     }
 
     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
@@ -1157,8 +1151,7 @@
         lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
-        final WindowManager wm = WindowManagerImpl.getDefault();
-        wm.updateViewLayout(mStatusBarWindow, lp);
+        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
 
         // Updating the window layout will force an expensive traversal/redraw.
         // Kick off the reveal animation after this is complete to avoid animation latency.
@@ -1231,8 +1224,7 @@
         lp.height = getStatusBarHeight();
         lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        final WindowManager wm = WindowManagerImpl.getDefault();
-        wm.updateViewLayout(mStatusBarWindow, lp);
+        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
 
         if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
             setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
@@ -1409,7 +1401,7 @@
 
     private void notifyUiVisibilityChanged() {
         try {
-            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+            mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
         } catch (RemoteException ex) {
         }
     }
@@ -1615,7 +1607,7 @@
         lp.packageName = mContext.getPackageName();
 
         makeStatusBarView();
-        WindowManagerImpl.getDefault().addView(mStatusBarWindow, lp);
+        mWindowManager.addView(mStatusBarWindow, lp);
     }
 
     void setNotificationIconVisibility(boolean visible, int anim) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 2a96d6d..6d474938 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -140,7 +140,7 @@
         super.panelExpansionChanged(pv, frac);
 
         if (mFadingPanel == pv 
-                && mScrimColor != 0 && ActivityManager.isHighEndGfx(mBar.mDisplay)) {
+                && mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
             // woo, special effects
             final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
             // attenuate background color alpha by k
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index ddb43b8..2924cc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -34,7 +34,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
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 cbd8831..84697e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -53,7 +53,6 @@
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -124,8 +123,6 @@
     int mMenuNavIconWidth = -1;
     private int mMaxNotificationIcons = 5;
 
-    IWindowManager mWindowManager;
-
     TabletStatusBarView mStatusBarView;
     View mNotificationArea;
     View mNotificationTrigger;
@@ -241,7 +238,7 @@
         lp.gravity = getStatusBarGravity();
         lp.setTitle("SystemBar");
         lp.packageName = mContext.getPackageName();
-        WindowManagerImpl.getDefault().addView(sb, lp);
+        mWindowManager.addView(sb, lp);
     }
 
     protected void addPanelWindows() {
@@ -306,7 +303,7 @@
         lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
 //        lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
 
-        WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
+        mWindowManager.addView(mNotificationPanel, lp);
 
         // Recents Panel
         mRecentTasksLoader = new RecentTasksLoader(context);
@@ -338,7 +335,7 @@
         lp.setTitle("InputMethodsPanel");
         lp.windowAnimations = R.style.Animation_RecentPanel;
 
-        WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
+        mWindowManager.addView(mInputMethodsPanel, lp);
 
         // Compatibility mode selector panel
         mCompatModePanel = (CompatModePanel) View.inflate(context,
@@ -361,7 +358,7 @@
         lp.setTitle("CompatModePanel");
         lp.windowAnimations = android.R.style.Animation_Dialog;
 
-        WindowManagerImpl.getDefault().addView(mCompatModePanel, lp);
+        mWindowManager.addView(mCompatModePanel, lp);
 
         mRecentButton.setOnTouchListener(mRecentsPanel);
 
@@ -380,7 +377,7 @@
 
     private int getNotificationPanelHeight() {
         final Resources res = mContext.getResources();
-        final Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+        final Display d = mWindowManager.getDefaultDisplay();
         final Point size = new Point();
         d.getRealSize(size);
         return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height), size.y);
@@ -395,8 +392,7 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         loadDimens();
         mNotificationPanelParams.height = getNotificationPanelHeight();
-        WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
-                mNotificationPanelParams);
+        mWindowManager.updateViewLayout(mNotificationPanel, mNotificationPanelParams);
         mRecentsPanel.updateValuesFromResources();
         mShowSearchHoldoff = mContext.getResources().getInteger(
                 R.integer.config_show_search_delay);
@@ -456,9 +452,6 @@
     protected View makeStatusBarView() {
         final Context context = mContext;
 
-        mWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
-
         loadDimens();
 
         final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
@@ -470,7 +463,7 @@
         try {
             // Sanity-check that someone hasn't set up the config wrong and asked for a navigation
             // bar on a tablet that has only the system bar
-            if (mWindowManager.hasNavigationBar()) {
+            if (mWindowManagerService.hasNavigationBar()) {
                 Slog.e(TAG, "Tablet device cannot show navigation bar and system bar");
             }
         } catch (RemoteException ex) {
@@ -648,7 +641,7 @@
                         | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                         | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
+        if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         } else {
             lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
@@ -681,7 +674,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
         lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp);
+        mWindowManager.updateViewLayout(mStatusBarView, lp);
     }
 
     @Override
@@ -690,7 +683,7 @@
         WindowManager.LayoutParams lp =
             (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
         lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-        WindowManagerImpl.getDefault().updateViewLayout(mStatusBarView, lp);
+        mWindowManager.updateViewLayout(mStatusBarView, lp);
     }
 
     public int getStatusBarHeight() {
@@ -712,8 +705,7 @@
         }
         if (lp.height != height) {
             lp.height = height;
-            final WindowManager wm = WindowManagerImpl.getDefault();
-            wm.updateViewLayout(mStatusBarView, lp);
+            mWindowManager.updateViewLayout(mStatusBarView, lp);
         }
     }
 
@@ -1068,7 +1060,7 @@
 
     private void notifyUiVisibilityChanged() {
         try {
-            mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
+            mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
         } catch (RemoteException ex) {
         }
     }
@@ -1160,12 +1152,12 @@
                 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
         lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
 
-        WindowManagerImpl.getDefault().addView(mCompatibilityHelpDialog, lp);
+        mWindowManager.addView(mCompatibilityHelpDialog, lp);
     }
 
     private void hideCompatibilityHelp() {
         if (mCompatibilityHelpDialog != null) {
-            WindowManagerImpl.getDefault().removeView(mCompatibilityHelpDialog);
+            mWindowManager.removeView(mCompatibilityHelpDialog);
             mCompatibilityHelpDialog = null;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index d4ebe6d..932b035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -35,7 +35,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.FrameLayout;
@@ -62,7 +61,8 @@
 
     private static final int ADVANCE_DELAY = 5000; // 5 seconds
 
-    private Context mContext;
+    private final Context mContext;
+    private final WindowManager mWindowManager;
 
     private ViewGroup mWindow;
     private IBinder mCurrentKey;
@@ -83,6 +83,7 @@
     public TabletTicker(TabletStatusBar bar) {
         mBar = bar;
         mContext = bar.getContext();
+        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
         final Resources res = mContext.getResources();
         mLargeIconHeight = res.getDimensionPixelSize(
                 android.R.dimen.notification_large_icon_height);
@@ -178,7 +179,7 @@
             if (mCurrentView != null) {
                 if (mWindow == null) {
                     mWindow = makeWindow();
-                    WindowManagerImpl.getDefault().addView(mWindow, mWindow.getLayoutParams());
+                    mWindowManager.addView(mWindow, mWindow.getLayoutParams());
                 }
 
                 mWindow.addView(mCurrentView);
@@ -242,7 +243,7 @@
     public void endTransition(LayoutTransition transition, ViewGroup container,
             View view, int transitionType) {
         if (mWindowShouldClose) {
-            WindowManagerImpl.getDefault().removeView(mWindow);
+            mWindowManager.removeView(mWindow);
             mWindow = null;
             mWindowShouldClose = false;
             mBar.doneTicking();
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
new file mode 100644
index 0000000..9146ccd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 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 com.android.systemui.usb;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Typeface;
+import android.hardware.usb.IUsbManager;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+
+import com.android.systemui.R;
+
+public class UsbDebuggingActivity extends AlertActivity
+                                  implements DialogInterface.OnClickListener {
+    private static final String TAG = "UsbDebuggingActivity";
+
+    private CheckBox mAlwaysAllow;
+    private UsbDisconnectedReceiver mDisconnectedReceiver;
+    private String mKey;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mDisconnectedReceiver = new UsbDisconnectedReceiver(this);
+        Intent intent = getIntent();
+        String fingerprints = intent.getStringExtra("fingerprints");
+        mKey = intent.getStringExtra("key");
+
+        if (fingerprints == null || mKey == null) {
+            finish();
+            return;
+        }
+
+        final AlertController.AlertParams ap = mAlertParams;
+        ap.mTitle = getString(R.string.usb_debugging_title);
+        ap.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
+        ap.mMessage = getString(R.string.usb_debugging_message, fingerprints);
+        ap.mPositiveButtonText = getString(android.R.string.ok);
+        ap.mNegativeButtonText = getString(android.R.string.cancel);
+        ap.mPositiveButtonListener = this;
+        ap.mNegativeButtonListener = this;
+
+        // add "always allow" checkbox
+        LayoutInflater inflater = LayoutInflater.from(ap.mContext);
+        View checkbox = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
+        mAlwaysAllow = (CheckBox)checkbox.findViewById(com.android.internal.R.id.alwaysUse);
+        mAlwaysAllow.setText(getString(R.string.usb_debugging_always));
+        ap.mView = checkbox;
+
+        setupAlert();
+    }
+
+    private class UsbDisconnectedReceiver extends BroadcastReceiver {
+        private final Activity mActivity;
+        public UsbDisconnectedReceiver(Activity activity) {
+            mActivity = activity;
+        }
+
+        @Override
+        public void onReceive(Context content, Intent intent) {
+            String action = intent.getAction();
+            if (!UsbManager.ACTION_USB_STATE.equals(action)) {
+                return;
+            }
+            boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
+            if (!connected) {
+                mActivity.finish();
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
+        registerReceiver(mDisconnectedReceiver, filter);
+    }
+
+    @Override
+    protected void onStop() {
+        if (mDisconnectedReceiver != null) {
+            unregisterReceiver(mDisconnectedReceiver);
+        }
+        super.onStop();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        boolean allow = (which == AlertDialog.BUTTON_POSITIVE);
+        boolean alwaysAllow = allow && mAlwaysAllow.isChecked();
+        try {
+            IBinder b = ServiceManager.getService(USB_SERVICE);
+            IUsbManager service = IUsbManager.Stub.asInterface(b);
+            if (allow) {
+                service.allowUsbDebugging(alwaysAllow, mKey);
+            } else {
+                service.denyUsbDebugging();
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Unable to notify Usb service", e);
+        }
+        finish();
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index a0e3e3c..8d19f34 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -50,6 +50,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicy.WindowManagerFuncs;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
@@ -90,8 +91,6 @@
     private boolean mHasTelephony;
     private boolean mHasVibrator;
 
-    private IWindowManager mIWindowManager;
-
     /**
      * @param context everything needs a context :(
      */
@@ -210,11 +209,11 @@
 
                 public void onPress() {
                     // shutdown by making sure radio and power are handled accordingly.
-                    mWindowManagerFuncs.shutdown();
+                    mWindowManagerFuncs.shutdown(true);
                 }
 
                 public boolean onLongPress() {
-                    mWindowManagerFuncs.rebootSafeMode();
+                    mWindowManagerFuncs.rebootSafeMode(true);
                     return true;
                 }
 
@@ -300,7 +299,7 @@
                     public void onPress() {
                         try {
                             ActivityManagerNative.getDefault().switchUser(user.id);
-                            getWindowManager().lockNow();
+                            WindowManagerGlobal.getWindowManagerService().lockNow();
                         } catch (RemoteException re) {
                             Log.e(TAG, "Couldn't switch user " + re);
                         }
@@ -873,12 +872,4 @@
             mAirplaneState = on ? ToggleAction.State.On : ToggleAction.State.Off;
         }
     }
-
-    private IWindowManager getWindowManager() {
-        if (mIWindowManager == null) {
-            IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
-            mIWindowManager = IWindowManager.Stub.asInterface(b);
-        }
-        return mIWindowManager;
-    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 279314d..5c0cd4f 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -259,7 +259,8 @@
          */
         boolean isPluggedIn() {
             return plugged == BatteryManager.BATTERY_PLUGGED_AC
-                    || plugged == BatteryManager.BATTERY_PLUGGED_USB;
+                    || plugged == BatteryManager.BATTERY_PLUGGED_USB
+                    || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
         }
 
         /**
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index fb6ff24..d521c05 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -123,8 +123,7 @@
             if (!mNeedsInput) {
                 flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
             }
-            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
-                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
+            if (ActivityManager.isHighEndGfx()) {
                 flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
             }
             WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
@@ -132,8 +131,7 @@
                     flags, PixelFormat.TRANSLUCENT);
             lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
             lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
-            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.getSystemService(
-                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
+            if (ActivityManager.isHighEndGfx()) {
                 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
                 lp.privateFlags |=
                         WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 66ccdac..4d05a87 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -44,7 +44,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.view.KeyEvent;
-import android.view.WindowManagerImpl;
+import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 
 
@@ -376,9 +376,9 @@
         mKeyguardViewProperties
                 = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
 
+        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
         mKeyguardViewManager = new KeyguardViewManager(
-                context, WindowManagerImpl.getDefault(), this,
-                mKeyguardViewProperties, mUpdateMonitor);
+                context, wm, this, mKeyguardViewProperties, mUpdateMonitor);
 
         mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
         mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 737df7f..209ad38 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -42,6 +42,7 @@
 import android.media.IAudioService;
 import android.os.BatteryManager;
 import android.os.Bundle;
+import android.os.FactoryTest;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
@@ -82,6 +83,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.WindowManagerGlobal;
 import android.view.WindowOrientationListener;
 import android.view.Surface;
 import android.view.View;
@@ -132,7 +134,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
@@ -172,6 +173,7 @@
     static final int LONG_PRESS_POWER_NOTHING = 0;
     static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
     static final int LONG_PRESS_POWER_SHUT_OFF = 2;
+    static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
 
     // These need to match the documentation/constant in
     // core/res/res/values/config.xml
@@ -716,8 +718,12 @@
         public void run() {
             // The context isn't read
             if (mLongPressOnPowerBehavior < 0) {
-                mLongPressOnPowerBehavior = mContext.getResources().getInteger(
-                        com.android.internal.R.integer.config_longPressOnPowerBehavior);
+                if (FactoryTest.isLongPressOnPowerOffEnabled()) {
+                    mLongPressOnPowerBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
+                } else {
+                    mLongPressOnPowerBehavior = mContext.getResources().getInteger(
+                            com.android.internal.R.integer.config_longPressOnPowerBehavior);
+                }
             }
             switch (mLongPressOnPowerBehavior) {
             case LONG_PRESS_POWER_NOTHING:
@@ -729,10 +735,12 @@
                 showGlobalActionsDialog();
                 break;
             case LONG_PRESS_POWER_SHUT_OFF:
+            case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
                 mPowerKeyHandled = true;
                 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
-                mWindowManagerFuncs.shutdown();
+                mWindowManagerFuncs.shutdown(
+                        mLongPressOnPowerBehavior == LONG_PRESS_POWER_SHUT_OFF);
                 break;
             }
         }
@@ -1172,7 +1180,7 @@
         
         if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
                 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
-            return WindowManagerImpl.ADD_OKAY;
+            return WindowManagerGlobal.ADD_OKAY;
         }
         String permission = null;
         switch (type) {
@@ -1199,10 +1207,10 @@
         if (permission != null) {
             if (mContext.checkCallingOrSelfPermission(permission)
                     != PackageManager.PERMISSION_GRANTED) {
-                return WindowManagerImpl.ADD_PERMISSION_DENIED;
+                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
             }
         }
-        return WindowManagerImpl.ADD_OKAY;
+        return WindowManagerGlobal.ADD_OKAY;
     }
     
     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
@@ -1499,7 +1507,7 @@
             // Only return the view if it was successfully added to the
             // window manager... which we can tell by it having a parent.
             return view.getParent() != null ? view : null;
-        } catch (WindowManagerImpl.BadTokenException e) {
+        } catch (WindowManager.BadTokenException e) {
             // ignore
             Log.w(TAG, appToken + " already running, starting window not displayed");
         } catch (RuntimeException e) {
@@ -1538,7 +1546,8 @@
      * @param win The window to be added
      * @param attrs Information about the window to be added
      * 
-     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
+     * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons,
+     * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
      */
     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
         switch (attrs.type) {
@@ -1548,7 +1557,7 @@
                         "PhoneWindowManager");
                 if (mStatusBar != null) {
                     if (mStatusBar.isAlive()) {
-                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                     }
                 }
                 mStatusBar = win;
@@ -1559,7 +1568,7 @@
                         "PhoneWindowManager");
                 if (mNavigationBar != null) {
                     if (mNavigationBar.isAlive()) {
-                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                        return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                     }
                 }
                 mNavigationBar = win;
@@ -1582,12 +1591,12 @@
                 break;
             case TYPE_KEYGUARD:
                 if (mKeyguard != null) {
-                    return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                    return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
                 }
                 mKeyguard = win;
                 break;
         }
-        return WindowManagerImpl.ADD_OKAY;
+        return WindowManagerGlobal.ADD_OKAY;
     }
 
     /** {@inheritDoc} */
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 0a6f23c..6ae16a4 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -93,6 +93,7 @@
 
     private boolean mAcOnline;
     private boolean mUsbOnline;
+    private boolean mWirelessOnline;
     private int mBatteryStatus;
     private int mBatteryHealth;
     private boolean mBatteryPresent;
@@ -150,7 +151,8 @@
 
     public final boolean isPowered() {
         // assume we are powered if battery state is unknown so the "stay on while plugged in" option will work.
-        return (mAcOnline || mUsbOnline || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
+        return (mAcOnline || mUsbOnline || mWirelessOnline
+                || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
     }
 
     public final boolean isPowered(int plugTypeSet) {
@@ -169,6 +171,9 @@
         if (mUsbOnline) {
             plugTypeBit |= BatteryManager.BATTERY_PLUGGED_USB;
         }
+        if (mWirelessOnline) {
+            plugTypeBit |= BatteryManager.BATTERY_PLUGGED_WIRELESS;
+        }
         return (plugTypeSet & plugTypeBit) != 0;
     }
 
@@ -243,6 +248,8 @@
             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
         } else if (mUsbOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
+        } else if (mWirelessOnline) {
+            mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
         } else {
             mPlugType = BATTERY_PLUGGED_NONE;
         }
@@ -398,6 +405,7 @@
                     " temperature: " + mBatteryTemperature +
                     " technology: " + mBatteryTechnology +
                     " AC powered:" + mAcOnline + " USB powered:" + mUsbOnline +
+                    " Wireless powered:" + mWirelessOnline +
                     " icon:" + icon  + " invalid charger:" + mInvalidCharger);
         }
 
@@ -503,6 +511,7 @@
                 pw.println("Current Battery Service state:");
                 pw.println("  AC powered: " + mAcOnline);
                 pw.println("  USB powered: " + mUsbOnline);
+                pw.println("  Wireless powered: " + mWirelessOnline);
                 pw.println("  status: " + mBatteryStatus);
                 pw.println("  health: " + mBatteryHealth);
                 pw.println("  present: " + mBatteryPresent);
@@ -523,6 +532,8 @@
                         mAcOnline = Integer.parseInt(value) != 0;
                     } else if ("usb".equals(key)) {
                         mUsbOnline = Integer.parseInt(value) != 0;
+                    } else if ("wireless".equals(key)) {
+                        mWirelessOnline = Integer.parseInt(value) != 0;
                     } else if ("status".equals(key)) {
                         mBatteryStatus = Integer.parseInt(value);
                     } else if ("level".equals(key)) {
@@ -603,4 +614,3 @@
         }
     }
 }
-
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 375ba68..cb6ce4b 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2592,6 +2592,11 @@
                     //       @see bug/4455071
                     handleConnectivityChange(info.getType(), false);
                     break;
+                case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
+                    info = (NetworkInfo) msg.obj;
+                    type = info.getType();
+                    updateNetworkSettings(mNetTrackers[type]);
+                    break;
             }
         }
     }
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 8bdd7be..ef09b01 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -18,10 +18,6 @@
 
 import static android.provider.Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK;
 
-import com.android.server.power.PowerManagerService;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -30,6 +26,7 @@
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -47,7 +44,7 @@
 /**
  * <p>DockObserver monitors for a docking station.
  */
-class DockObserver extends UEventObserver {
+final class DockObserver extends UEventObserver {
     private static final String TAG = DockObserver.class.getSimpleName();
     private static final boolean LOG = false;
 
@@ -56,7 +53,9 @@
 
     private static final int DEFAULT_DOCK = 1;
 
-    private static final int MSG_DOCK_STATE = 0;
+    private static final int MSG_DOCK_STATE_CHANGED = 0;
+
+    private final Object mLock = new Object();
 
     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     private int mPreviousDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@@ -78,7 +77,7 @@
             Slog.v(TAG, "Dock UEVENT: " + event.toString());
         }
 
-        synchronized (this) {
+        synchronized (mLock) {
             try {
                 int newState = Integer.parseInt(event.get("SWITCH_STATE"));
                 if (newState != mDockState) {
@@ -96,7 +95,7 @@
                                     (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
                             pm.wakeUp(SystemClock.uptimeMillis());
                         }
-                        update();
+                        updateLocked();
                     }
                 }
             } catch (NumberFormatException e) {
@@ -105,132 +104,142 @@
         }
     }
 
-    private final void init() {
-        char[] buffer = new char[1024];
-
-        try {
-            FileReader file = new FileReader(DOCK_STATE_PATH);
-            int len = file.read(buffer, 0, 1024);
-            file.close();
-            mPreviousDockState = mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
-        } catch (FileNotFoundException e) {
-            Slog.w(TAG, "This kernel does not have dock station support");
-        } catch (Exception e) {
-            Slog.e(TAG, "" , e);
+    private void init() {
+        synchronized (mLock) {
+            try {
+                char[] buffer = new char[1024];
+                FileReader file = new FileReader(DOCK_STATE_PATH);
+                try {
+                    int len = file.read(buffer, 0, 1024);
+                    mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
+                    mPreviousDockState = mDockState;
+                } finally {
+                    file.close();
+                }
+            } catch (FileNotFoundException e) {
+                Slog.w(TAG, "This kernel does not have dock station support");
+            } catch (Exception e) {
+                Slog.e(TAG, "" , e);
+            }
         }
     }
 
     void systemReady() {
-        synchronized (this) {
+        synchronized (mLock) {
             // don't bother broadcasting undocked here
             if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                update();
+                updateLocked();
             }
             mSystemReady = true;
         }
     }
 
-    private final void update() {
-        mHandler.sendEmptyMessage(MSG_DOCK_STATE);
+    private void updateLocked() {
+        mHandler.sendEmptyMessage(MSG_DOCK_STATE_CHANGED);
+    }
+
+    private void handleDockStateChange() {
+        synchronized (mLock) {
+            Slog.i(TAG, "Dock state changed: " + mDockState);
+
+            final ContentResolver cr = mContext.getContentResolver();
+
+            if (Settings.Secure.getInt(cr,
+                    Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
+                Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
+                return;
+            }
+
+            // Pack up the values and broadcast them to everyone
+            Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+
+            // Check if this is Bluetooth Dock
+            // TODO(BT): Get Dock address.
+            // String address = null;
+            // if (address != null) {
+            //    intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
+            //            BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
+            // }
+
+            // User feedback to confirm dock connection. Particularly
+            // useful for flaky contact pins...
+            if (Settings.System.getInt(cr,
+                    Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1) {
+                String whichSound = null;
+                if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                    if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
+                        (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+                        (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
+                        whichSound = Settings.System.DESK_UNDOCK_SOUND;
+                    } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                        whichSound = Settings.System.CAR_UNDOCK_SOUND;
+                    }
+                } else {
+                    if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
+                        (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
+                        (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
+                        whichSound = Settings.System.DESK_DOCK_SOUND;
+                    } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                        whichSound = Settings.System.CAR_DOCK_SOUND;
+                    }
+                }
+
+                if (whichSound != null) {
+                    final String soundPath = Settings.System.getString(cr, whichSound);
+                    if (soundPath != null) {
+                        final Uri soundUri = Uri.parse("file://" + soundPath);
+                        if (soundUri != null) {
+                            final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                            if (sfx != null) {
+                                sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                                sfx.play();
+                            }
+                        }
+                    }
+                }
+            }
+
+            IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
+            if (mgr != null) {
+                // dreams feature enabled
+                boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED;
+                if (undocked) {
+                    try {
+                        if (mgr.isDreaming()) {
+                            mgr.awaken();
+                        }
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "Unable to awaken!", e);
+                    }
+                } else {
+                    if (isScreenSaverActivatedOnDock(mContext)) {
+                        try {
+                            mgr.dream();
+                        } catch (RemoteException e) {
+                            Slog.w(TAG, "Unable to dream!", e);
+                        }
+                    }
+                }
+            } else {
+                // dreams feature not enabled, send legacy intent
+                mContext.sendStickyBroadcast(intent);
+            }
+        }
     }
 
     private static boolean isScreenSaverActivatedOnDock(Context context) {
-        return 0 != Settings.Secure.getInt(
-                    context.getContentResolver(), SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_DOCK);
+        return Settings.Secure.getInt(context.getContentResolver(),
+                SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_DOCK) != 0;
     }
 
-    private final Handler mHandler = new Handler() {
+    private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_DOCK_STATE:
-                    synchronized (this) {
-                        Slog.i(TAG, "Dock state changed: " + mDockState);
-
-                        final ContentResolver cr = mContext.getContentResolver();
-
-                        if (Settings.Secure.getInt(cr,
-                                Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
-                            Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
-                            return;
-                        }
-                        // Pack up the values and broadcast them to everyone
-                        Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
-                        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-                        intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
-
-                        // Check if this is Bluetooth Dock
-                        // TODO(BT): Get Dock address.
-                        String address = null;
-                        if (address != null)
-                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
-                                    BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
-
-                        // User feedback to confirm dock connection. Particularly
-                        // useful for flaky contact pins...
-                        if (Settings.System.getInt(cr,
-                                Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1)
-                        {
-                            String whichSound = null;
-                            if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
-                                if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
-                                    (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
-                                    (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
-                                    whichSound = Settings.System.DESK_UNDOCK_SOUND;
-                                } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
-                                    whichSound = Settings.System.CAR_UNDOCK_SOUND;
-                                }
-                            } else {
-                                if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
-                                    (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
-                                    (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
-                                    whichSound = Settings.System.DESK_DOCK_SOUND;
-                                } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
-                                    whichSound = Settings.System.CAR_DOCK_SOUND;
-                                }
-                            }
-
-                            if (whichSound != null) {
-                                final String soundPath = Settings.System.getString(cr, whichSound);
-                                if (soundPath != null) {
-                                    final Uri soundUri = Uri.parse("file://" + soundPath);
-                                    if (soundUri != null) {
-                                        final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                                        if (sfx != null) {
-                                            sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                                            sfx.play();
-                                        }
-                                    }
-                                }
-                            }
-                        }
-
-                        IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
-                        if (mgr != null) {
-                            // dreams feature enabled
-                            boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED;
-                            if (undocked) {
-                                try {
-                                    if (mgr.isDreaming()) {
-                                        mgr.awaken();
-                                    }
-                                } catch (RemoteException e) {
-                                    Slog.w(TAG, "Unable to awaken!", e);
-                                }
-                            } else {
-                                if (isScreenSaverActivatedOnDock(mContext)) {
-                                    try {
-                                        mgr.dream();
-                                    } catch (RemoteException e) {
-                                        Slog.w(TAG, "Unable to dream!", e);
-                                    }
-                                }
-                            }
-                        } else {
-                            // dreams feature not enabled, send legacy intent
-                            mContext.sendStickyBroadcast(intent);
-                        }
-                    }
+                case MSG_DOCK_STATE_CHANGED:
+                    handleDockStateChange();
                     break;
             }
         }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index a565d08..d6fed39 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -1272,7 +1272,7 @@
 
     void checkCallerIsSystem() {
         int uid = Binder.getCallingUid();
-        if (uid == Process.SYSTEM_UID || uid == 0) {
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
             return;
         }
         throw new SecurityException("Disallowed call for uid " + uid);
@@ -1280,7 +1280,7 @@
 
     void checkCallerIsSystemOrSameApp(String pkg) {
         int uid = Binder.getCallingUid();
-        if (uid == Process.SYSTEM_UID || uid == 0) {
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
             return;
         }
         try {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c471dd2..a117b06 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -155,13 +155,12 @@
             power = new PowerManagerService();
             ServiceManager.addService(Context.POWER_SERVICE, power);
 
-            Slog.i(TAG, "Display Manager");
-            display = new DisplayManagerService();
-            ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
-
             Slog.i(TAG, "Activity Manager");
             context = ActivityManagerService.main(factoryTest);
-            display.setContext(context);
+
+            Slog.i(TAG, "Display Manager");
+            display = new DisplayManagerService(context);
+            ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
 
             Slog.i(TAG, "Telephony Registry");
             ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 1d248b2..afd7d0e 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -768,10 +768,6 @@
             WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
             intent.setComponent(componentName);
             int serviceUserId = wallpaper.userId;
-            // Because the image wallpaper is running in the system ui
-            if (componentName.equals(wallpaper.imageWallpaperComponent)) {
-                serviceUserId = 0;
-            }
             intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                     com.android.internal.R.string.wallpaper_binding_label);
             intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index 96ac493..56c0fdf 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -16,12 +16,12 @@
 
 package com.android.server;
 
-import android.app.ActivityManagerNative;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
@@ -39,7 +39,7 @@
 /**
  * <p>WiredAccessoryObserver monitors for a wired headset on the main board or dock.
  */
-class WiredAccessoryObserver extends UEventObserver {
+final class WiredAccessoryObserver extends UEventObserver {
     private static final String TAG = WiredAccessoryObserver.class.getSimpleName();
     private static final boolean LOG = true;
     private static final int BIT_HEADSET = (1 << 0);
@@ -50,40 +50,177 @@
     private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_NO_MIC|
                                                    BIT_USB_HEADSET_ANLG|BIT_USB_HEADSET_DGTL|
                                                    BIT_HDMI_AUDIO);
-    private static final int HEADSETS_WITH_MIC = BIT_HEADSET;
 
-    private static class UEventInfo {
-        private final String mDevName;
-        private final int mState1Bits;
-        private final int mState2Bits;
+    private final Object mLock = new Object();
 
-        public UEventInfo(String devName, int state1Bits, int state2Bits) {
-            mDevName = devName;
-            mState1Bits = state1Bits;
-            mState2Bits = state2Bits;
+    private final Context mContext;
+    private final WakeLock mWakeLock;  // held while there is a pending route change
+    private final AudioManager mAudioManager;
+    private final List<UEventInfo> mUEventInfo;
+
+    private int mHeadsetState;
+    private int mPrevHeadsetState;
+    private String mHeadsetName;
+
+    public WiredAccessoryObserver(Context context) {
+        mContext = context;
+
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver");
+        mWakeLock.setReferenceCounted(false);
+        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+
+        mUEventInfo = makeObservedUEventList();
+
+        context.registerReceiver(new BootCompletedReceiver(),
+            new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+    }
+
+    @Override
+    public void onUEvent(UEventObserver.UEvent event) {
+        if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
+
+        try {
+            String devPath = event.get("DEVPATH");
+            String name = event.get("SWITCH_NAME");
+            int state = Integer.parseInt(event.get("SWITCH_STATE"));
+            synchronized (mLock) {
+                updateStateLocked(devPath, name, state);
+            }
+        } catch (NumberFormatException e) {
+            Slog.e(TAG, "Could not parse switch state from event " + event);
+        }
+    }
+
+    private void bootCompleted() {
+        synchronized (mLock) {
+            char[] buffer = new char[1024];
+            mPrevHeadsetState = mHeadsetState;
+
+            if (LOG) Slog.v(TAG, "init()");
+
+            for (int i = 0; i < mUEventInfo.size(); ++i) {
+                UEventInfo uei = mUEventInfo.get(i);
+                try {
+                    int curState;
+                    FileReader file = new FileReader(uei.getSwitchStatePath());
+                    int len = file.read(buffer, 0, 1024);
+                    file.close();
+                    curState = Integer.valueOf((new String(buffer, 0, len)).trim());
+
+                    if (curState > 0) {
+                        updateStateLocked(uei.getDevPath(), uei.getDevName(), curState);
+                    }
+                } catch (FileNotFoundException e) {
+                    Slog.w(TAG, uei.getSwitchStatePath() +
+                            " not found while attempting to determine initial switch state");
+                } catch (Exception e) {
+                    Slog.e(TAG, "" , e);
+                }
+            }
         }
 
-        public String getDevName() { return mDevName; }
+        // At any given time accessories could be inserted
+        // one on the board, one on the dock and one on HDMI:
+        // observe three UEVENTs
+        for (int i = 0; i < mUEventInfo.size(); ++i) {
+            UEventInfo uei = mUEventInfo.get(i);
+            startObserving("DEVPATH="+uei.getDevPath());
+        }
+    }
 
-        public String getDevPath() {
-            return String.format("/devices/virtual/switch/%s", mDevName);
+    private void updateStateLocked(String devPath, String name, int state) {
+        for (int i = 0; i < mUEventInfo.size(); ++i) {
+            UEventInfo uei = mUEventInfo.get(i);
+            if (devPath.equals(uei.getDevPath())) {
+                updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state));
+                return;
+            }
+        }
+    }
+
+    private void updateLocked(String newName, int newState) {
+        // Retain only relevant bits
+        int headsetState = newState & SUPPORTED_HEADSETS;
+        int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
+        int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
+        int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
+        boolean h2wStateChange = true;
+        boolean usbStateChange = true;
+        // reject all suspect transitions: only accept state changes from:
+        // - a: 0 heaset to 1 headset
+        // - b: 1 headset to 0 headset
+        if (LOG) Slog.v(TAG, "newState = "+newState+", headsetState = "+headsetState+","
+            + "mHeadsetState = "+mHeadsetState);
+        if (mHeadsetState == headsetState || ((h2w_headset & (h2w_headset - 1)) != 0)) {
+            Log.e(TAG, "unsetting h2w flag");
+            h2wStateChange = false;
+        }
+        // - c: 0 usb headset to 1 usb headset
+        // - d: 1 usb headset to 0 usb headset
+        if ((usb_headset_anlg >> 2) == 1 && (usb_headset_dgtl >> 3) == 1) {
+            Log.e(TAG, "unsetting usb flag");
+            usbStateChange = false;
+        }
+        if (!h2wStateChange && !usbStateChange) {
+            Log.e(TAG, "invalid transition, returning ...");
+            return;
         }
 
-        public String getSwitchStatePath() {
-            return String.format("/sys/class/switch/%s/state", mDevName);
+        mHeadsetName = newName;
+        mPrevHeadsetState = mHeadsetState;
+        mHeadsetState = headsetState;
+
+        mWakeLock.acquire();
+
+        Message msg = mHandler.obtainMessage(0, mHeadsetState, mPrevHeadsetState, mHeadsetName);
+        mHandler.sendMessage(msg);
+    }
+
+    private void setDevicesState(
+            int headsetState, int prevHeadsetState, String headsetName) {
+        synchronized (mLock) {
+            int allHeadsets = SUPPORTED_HEADSETS;
+            for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
+                if ((curHeadset & allHeadsets) != 0) {
+                    setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);
+                    allHeadsets &= ~curHeadset;
+                }
+            }
         }
+    }
 
-        public boolean checkSwitchExists() {
-            File f = new File(getSwitchStatePath());
-            return ((null != f) && f.exists());
-        }
+    private void setDeviceStateLocked(int headset,
+            int headsetState, int prevHeadsetState, String headsetName) {
+        if ((headsetState & headset) != (prevHeadsetState & headset)) {
+            int device;
+            int state;
 
-        public int computeNewHeadsetState(int headsetState, int switchState) {
-            int preserveMask = ~(mState1Bits | mState2Bits);
-            int setBits = ((switchState == 1) ? mState1Bits :
-                          ((switchState == 2) ? mState2Bits : 0));
+            if ((headsetState & headset) != 0) {
+                state = 1;
+            } else {
+                state = 0;
+            }
 
-            return ((headsetState & preserveMask) | setBits);
+            if (headset == BIT_HEADSET) {
+                device = AudioManager.DEVICE_OUT_WIRED_HEADSET;
+            } else if (headset == BIT_HEADSET_NO_MIC){
+                device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
+            } else if (headset == BIT_USB_HEADSET_ANLG) {
+                device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
+            } else if (headset == BIT_USB_HEADSET_DGTL) {
+                device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
+            } else if (headset == BIT_HDMI_AUDIO) {
+                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
+            } else {
+                Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
+                return;
+            }
+
+            if (LOG)
+                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
+
+            mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
         }
     }
 
@@ -130,189 +267,53 @@
         return retVal;
     }
 
-    private static List<UEventInfo> uEventInfo = makeObservedUEventList();
-
-    private int mHeadsetState;
-    private int mPrevHeadsetState;
-    private String mHeadsetName;
-
-    private final Context mContext;
-    private final WakeLock mWakeLock;  // held while there is a pending route change
-
-    private final AudioManager mAudioManager;
-
-    public WiredAccessoryObserver(Context context) {
-        mContext = context;
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver");
-        mWakeLock.setReferenceCounted(false);
-        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
-
-        context.registerReceiver(new BootCompletedReceiver(),
-            new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
-    }
-
-    private final class BootCompletedReceiver extends BroadcastReceiver {
-      @Override
-      public void onReceive(Context context, Intent intent) {
-        // At any given time accessories could be inserted
-        // one on the board, one on the dock and one on HDMI:
-        // observe three UEVENTs
-        init();  // set initial status
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            startObserving("DEVPATH="+uei.getDevPath());
-        }
-      }
-    }
-
-    @Override
-    public void onUEvent(UEventObserver.UEvent event) {
-        if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
-
-        try {
-            String devPath = event.get("DEVPATH");
-            String name = event.get("SWITCH_NAME");
-            int state = Integer.parseInt(event.get("SWITCH_STATE"));
-            updateState(devPath, name, state);
-        } catch (NumberFormatException e) {
-            Slog.e(TAG, "Could not parse switch state from event " + event);
-        }
-    }
-
-    private synchronized final void updateState(String devPath, String name, int state)
-    {
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            if (devPath.equals(uei.getDevPath())) {
-                update(name, uei.computeNewHeadsetState(mHeadsetState, state));
-                return;
-            }
-        }
-    }
-
-    private synchronized final void init() {
-        char[] buffer = new char[1024];
-        mPrevHeadsetState = mHeadsetState;
-
-        if (LOG) Slog.v(TAG, "init()");
-
-        for (int i = 0; i < uEventInfo.size(); ++i) {
-            UEventInfo uei = uEventInfo.get(i);
-            try {
-                int curState;
-                FileReader file = new FileReader(uei.getSwitchStatePath());
-                int len = file.read(buffer, 0, 1024);
-                file.close();
-                curState = Integer.valueOf((new String(buffer, 0, len)).trim());
-
-                if (curState > 0) {
-                    updateState(uei.getDevPath(), uei.getDevName(), curState);
-                }
-
-            } catch (FileNotFoundException e) {
-                Slog.w(TAG, uei.getSwitchStatePath() +
-                        " not found while attempting to determine initial switch state");
-            } catch (Exception e) {
-                Slog.e(TAG, "" , e);
-            }
-        }
-    }
-
-    private synchronized final void update(String newName, int newState) {
-        // Retain only relevant bits
-        int headsetState = newState & SUPPORTED_HEADSETS;
-        int newOrOld = headsetState | mHeadsetState;
-        int delay = 0;
-        int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
-        int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
-        int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
-        boolean h2wStateChange = true;
-        boolean usbStateChange = true;
-        // reject all suspect transitions: only accept state changes from:
-        // - a: 0 heaset to 1 headset
-        // - b: 1 headset to 0 headset
-        if (LOG) Slog.v(TAG, "newState = "+newState+", headsetState = "+headsetState+","
-            + "mHeadsetState = "+mHeadsetState);
-        if (mHeadsetState == headsetState || ((h2w_headset & (h2w_headset - 1)) != 0)) {
-            Log.e(TAG, "unsetting h2w flag");
-            h2wStateChange = false;
-        }
-        // - c: 0 usb headset to 1 usb headset
-        // - d: 1 usb headset to 0 usb headset
-        if ((usb_headset_anlg >> 2) == 1 && (usb_headset_dgtl >> 3) == 1) {
-            Log.e(TAG, "unsetting usb flag");
-            usbStateChange = false;
-        }
-        if (!h2wStateChange && !usbStateChange) {
-            Log.e(TAG, "invalid transition, returning ...");
-            return;
-        }
-
-        mHeadsetName = newName;
-        mPrevHeadsetState = mHeadsetState;
-        mHeadsetState = headsetState;
-
-        mWakeLock.acquire();
-        mHandler.sendMessage(mHandler.obtainMessage(0,
-                                                    mHeadsetState,
-                                                    mPrevHeadsetState,
-                                                    mHeadsetName));
-    }
-
-    private synchronized final void setDevicesState(int headsetState,
-                                                    int prevHeadsetState,
-                                                    String headsetName) {
-        int allHeadsets = SUPPORTED_HEADSETS;
-        for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
-            if ((curHeadset & allHeadsets) != 0) {
-                setDeviceState(curHeadset, headsetState, prevHeadsetState, headsetName);
-                allHeadsets &= ~curHeadset;
-            }
-        }
-    }
-
-    private final void setDeviceState(int headset,
-                                      int headsetState,
-                                      int prevHeadsetState,
-                                      String headsetName) {
-        if ((headsetState & headset) != (prevHeadsetState & headset)) {
-            int device;
-            int state;
-
-            if ((headsetState & headset) != 0) {
-                state = 1;
-            } else {
-                state = 0;
-            }
-
-            if (headset == BIT_HEADSET) {
-                device = AudioManager.DEVICE_OUT_WIRED_HEADSET;
-            } else if (headset == BIT_HEADSET_NO_MIC){
-                device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
-            } else if (headset == BIT_USB_HEADSET_ANLG) {
-                device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
-            } else if (headset == BIT_USB_HEADSET_DGTL) {
-                device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
-            } else if (headset == BIT_HDMI_AUDIO) {
-                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
-            } else {
-                Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
-                return;
-            }
-
-            if (LOG)
-                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
-
-            mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
-        }
-    }
-
-    private final Handler mHandler = new Handler() {
+    private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
         @Override
         public void handleMessage(Message msg) {
             setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
             mWakeLock.release();
         }
     };
+
+    private static final class UEventInfo {
+        private final String mDevName;
+        private final int mState1Bits;
+        private final int mState2Bits;
+
+        public UEventInfo(String devName, int state1Bits, int state2Bits) {
+            mDevName = devName;
+            mState1Bits = state1Bits;
+            mState2Bits = state2Bits;
+        }
+
+        public String getDevName() { return mDevName; }
+
+        public String getDevPath() {
+            return String.format("/devices/virtual/switch/%s", mDevName);
+        }
+
+        public String getSwitchStatePath() {
+            return String.format("/sys/class/switch/%s/state", mDevName);
+        }
+
+        public boolean checkSwitchExists() {
+            File f = new File(getSwitchStatePath());
+            return ((null != f) && f.exists());
+        }
+
+        public int computeNewHeadsetState(int headsetState, int switchState) {
+            int preserveMask = ~(mState1Bits | mState2Bits);
+            int setBits = ((switchState == 1) ? mState1Bits :
+                          ((switchState == 2) ? mState2Bits : 0));
+
+            return ((headsetState & preserveMask) | setBits);
+        }
+    }
+
+    private final class BootCompletedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            bootCompleted();
+        }
+    }
 }
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index d8ccabb..e222936 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -1725,21 +1725,53 @@
         ArrayList<ActivityManager.RunningServiceInfo> res
                 = new ArrayList<ActivityManager.RunningServiceInfo>();
 
-        int userId = UserHandle.getUserId(Binder.getCallingUid());
-        if (mServiceMap.getAllServices(userId).size() > 0) {
-            Iterator<ServiceRecord> it
-                    = mServiceMap.getAllServices(userId).iterator();
-            while (it.hasNext() && res.size() < maxNum) {
-                res.add(makeRunningServiceInfoLocked(it.next()));
-            }
-        }
+        final int uid = Binder.getCallingUid();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            if (ActivityManager.checkUidPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    uid) == PackageManager.PERMISSION_GRANTED) {
+                List<UserInfo> users = mAm.getUserManager().getUsers();
+                for (int ui=0; ui<users.size() && res.size() < maxNum; ui++) {
+                    final UserInfo user = users.get(ui);
+                    if (mServiceMap.getAllServices(user.id).size() > 0) {
+                        Iterator<ServiceRecord> it = mServiceMap.getAllServices(
+                                user.id).iterator();
+                        while (it.hasNext() && res.size() < maxNum) {
+                            res.add(makeRunningServiceInfoLocked(it.next()));
+                        }
+                    }
+                }
 
-        for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
-            ServiceRecord r = mRestartingServices.get(i);
-            ActivityManager.RunningServiceInfo info =
-                    makeRunningServiceInfoLocked(r);
-            info.restarting = r.nextRestartTime;
-            res.add(info);
+                for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
+                    ServiceRecord r = mRestartingServices.get(i);
+                    ActivityManager.RunningServiceInfo info =
+                            makeRunningServiceInfoLocked(r);
+                    info.restarting = r.nextRestartTime;
+                    res.add(info);
+                }
+            } else {
+                int userId = UserHandle.getUserId(uid);
+                if (mServiceMap.getAllServices(userId).size() > 0) {
+                    Iterator<ServiceRecord> it
+                            = mServiceMap.getAllServices(userId).iterator();
+                    while (it.hasNext() && res.size() < maxNum) {
+                        res.add(makeRunningServiceInfoLocked(it.next()));
+                    }
+                }
+
+                for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
+                    ServiceRecord r = mRestartingServices.get(i);
+                    if (r.userId == userId) {
+                        ActivityManager.RunningServiceInfo info =
+                                makeRunningServiceInfoLocked(r);
+                        info.restarting = r.nextRestartTime;
+                        res.add(info);
+                    }
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
 
         return res;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5e85e1a..7f2b69f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -27,7 +27,6 @@
 import com.android.server.SystemServer;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.pm.UserManagerService;
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.Zygote;
@@ -52,7 +51,6 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.Service;
 import android.app.backup.IBackupManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
@@ -145,7 +143,6 @@
 import java.io.StringWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -2539,7 +2536,6 @@
         
         // This is so super not safe, that only the system (or okay root)
         // can do it.
-        int userId = Binder.getOrigCallingUser();
         final int callingUid = Binder.getCallingUid();
         if (callingUid != 0 && callingUid != Process.myUid()) {
             throw new SecurityException(
@@ -2548,7 +2544,7 @@
 
         int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
-                null, null, null, null, options, userId);
+                null, null, null, null, options, UserHandle.getUserId(uid));
         return ret;
     }
 
@@ -8392,11 +8388,19 @@
         // assume our apps are happy - lazy create the list
         List<ActivityManager.ProcessErrorStateInfo> errList = null;
 
+        final boolean allUsers = ActivityManager.checkUidPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
+        int userId = UserHandle.getUserId(Binder.getCallingUid());
+
         synchronized (this) {
 
             // iterate across all processes
             for (int i=mLruProcesses.size()-1; i>=0; i--) {
                 ProcessRecord app = mLruProcesses.get(i);
+                if (!allUsers && app.userId != userId) {
+                    continue;
+                }
                 if ((app.thread != null) && (app.crashing || app.notResponding)) {
                     // This one's in trouble, so we'll generate a report for it
                     // crashes are higher priority (in case there's a crash *and* an anr)
@@ -8460,6 +8464,9 @@
         if (app.persistent) {
             outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
         }
+        if (app.hasActivities) {
+            outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
+        }
         outInfo.lastTrimLevel = app.trimMemoryLevel;
         int adj = app.curAdj;
         outInfo.importance = oomAdjToImportance(adj, outInfo);
@@ -8470,10 +8477,17 @@
         enforceNotIsolatedCaller("getRunningAppProcesses");
         // Lazy instantiation of list
         List<ActivityManager.RunningAppProcessInfo> runList = null;
+        final boolean allUsers = ActivityManager.checkUidPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
+        int userId = UserHandle.getUserId(Binder.getCallingUid());
         synchronized (this) {
             // Iterate across all processes
             for (int i=mLruProcesses.size()-1; i>=0; i--) {
                 ProcessRecord app = mLruProcesses.get(i);
+                if (!allUsers && app.userId != userId) {
+                    continue;
+                }
                 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
                     // Generate process state info for running application
                     ActivityManager.RunningAppProcessInfo currApp = 
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 0106114..5b3ff8d 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -18,6 +18,7 @@
 
 import android.app.IServiceConnection;
 import android.app.PendingIntent;
+import android.content.Context;
 
 import java.io.PrintWriter;
 
@@ -62,6 +63,33 @@
         sb.append("ConnectionRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(' ');
+        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
+            sb.append("CR ");
+        }
+        if ((flags&Context.BIND_DEBUG_UNBIND) != 0) {
+            sb.append("DBG ");
+        }
+        if ((flags&Context.BIND_NOT_FOREGROUND) != 0) {
+            sb.append("NOTFG ");
+        }
+        if ((flags&Context.BIND_ABOVE_CLIENT) != 0) {
+            sb.append("ABCLT ");
+        }
+        if ((flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+            sb.append("OOM ");
+        }
+        if ((flags&Context.BIND_WAIVE_PRIORITY) != 0) {
+            sb.append("WPRI ");
+        }
+        if ((flags&Context.BIND_IMPORTANT) != 0) {
+            sb.append("IMP ");
+        }
+        if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
+            sb.append("ACT ");
+        }
+        if ((flags&Context.BIND_NOT_VISIBLE) != 0) {
+            sb.append("NOTVIS ");
+        }
         if (serviceDead) {
             sb.append("DEAD ");
         }
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
index c94f714..0a92964 100644
--- a/services/java/com/android/server/am/IntentBindRecord.java
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
 
@@ -78,6 +79,20 @@
         intent = _intent;
     }
 
+    int collectFlags() {
+        int flags = 0;
+        if (apps.size() > 0) {
+            for (AppBindRecord app : apps.values()) {
+                if (app.connections.size() > 0) {
+                    for (ConnectionRecord conn : app.connections) {
+                        flags |= conn.flags;
+                    }
+                }
+            }
+        }
+        return flags;
+    }
+
     public String toString() {
         if (stringName != null) {
             return stringName;
@@ -86,6 +101,9 @@
         sb.append("IntentBindRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(' ');
+        if ((collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
+            sb.append("CR ");
+        }
         sb.append(service.shortName);
         sb.append(':');
         if (intent != null) {
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index ab2e428..15fbb98 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -127,7 +127,12 @@
                 Slog.i(TAG,
                         "Removing from providersByName name=" + name + " user="
                         + (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId));
-            getProvidersByName(optionalUserId).remove(name);
+            HashMap<String, ContentProviderRecord> map = getProvidersByName(optionalUserId);
+            // map returned by getProvidersByName wouldn't be null
+            map.remove(name);
+            if (map.size() == 0) {
+                mProvidersByNamePerUser.remove(optionalUserId);
+            }
         }
     }
 
@@ -141,7 +146,12 @@
                 Slog.i(TAG,
                         "Removing from providersByClass name=" + name + " user="
                         + (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId));
-            getProvidersByClass(optionalUserId).remove(name);
+            HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(optionalUserId);
+            // map returned by getProvidersByClass wouldn't be null
+            map.remove(name);
+            if (map.size() == 0) {
+                mProvidersByClassPerUser.remove(optionalUserId);
+            }
         }
     }
 
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 41386e4..5d60b9c 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -23,6 +23,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -260,6 +261,9 @@
                 IntentBindRecord b = it.next();
                 pw.print(prefix); pw.print("* IntentBindRecord{");
                         pw.print(Integer.toHexString(System.identityHashCode(b)));
+                        if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
+                            pw.append(" CREATE");
+                        }
                         pw.println("}:");
                 b.dumpInService(pw, prefix + "  ");
             }
diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/java/com/android/server/display/DisplayAdapter.java
index b623906..f9fa7a8 100644
--- a/services/java/com/android/server/display/DisplayAdapter.java
+++ b/services/java/com/android/server/display/DisplayAdapter.java
@@ -16,38 +16,33 @@
 
 package com.android.server.display;
 
-import android.view.Display;
-
 /**
- * A display adapter makes a single display devices available to the system.
+ * A display adapter makes zero or more display devices available to the system
+ * and provides facilities for discovering when displays are connected or disconnected.
  * <p>
  * For now, all display adapters are registered in the system server but
  * in principle it could be done from other processes.
  * </p>
  */
 public abstract class DisplayAdapter {
-    /** The current logical Display assignment for this adapter. Will change if other logical
-     * display is assigned to this adapter */
-    private int mDisplayId = Display.NO_DISPLAY;
-
-    /** Assign the displayId
-     * @hide */
-    public void setDisplayId(int displayId) {
-        mDisplayId = displayId;
-    }
-
-    /** Retrieve the displayId
-     * @hide */
-    public int getDisplayId() {
-        return mDisplayId;
-    }
-
     /**
-     * Gets the display adapter name.
+     * Gets the display adapter name for debugging purposes.
+     *
      * @return The display adapter name.
      */
     public abstract String getName();
 
-    // TODO: dynamically register display devices
-    public abstract DisplayDevice getDisplayDevice();
+    /**
+     * Registers the display adapter with the display manager.
+     * The display adapter should register any built-in display devices now.
+     * Other display devices can be registered dynamically later.
+     *
+     * @param listener The listener for callbacks.
+     */
+    public abstract void register(Listener listener);
+
+    public interface Listener {
+        public void onDisplayDeviceAdded(DisplayDevice device);
+        public void onDisplayDeviceRemoved(DisplayDevice device);
+    }
 }
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java
index 6d723f2..57002ff 100644
--- a/services/java/com/android/server/display/DisplayDevice.java
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -18,8 +18,20 @@
 
 /**
  * Represents a physical display device such as the built-in display
- * or an external monitor.
+ * an external monitor, or a WiFi display.
  */
 public abstract class DisplayDevice {
+    /**
+     * Gets the display adapter that makes the display device available.
+     *
+     * @return The display adapter.
+     */
+    public abstract DisplayAdapter getAdapter();
+
+    /**
+     * Gets information about the display device.
+     *
+     * @param outInfo The object to populate with the information.
+     */
     public abstract void getInfo(DisplayDeviceInfo outInfo);
 }
diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java
index c60c2e9..9c0f964 100644
--- a/services/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.java
@@ -21,6 +21,12 @@
  */
 public final class DisplayDeviceInfo {
     /**
+     * Gets the name of the display device, which may be derived from
+     * EDID or other sources.  The name may be displayed to the user.
+     */
+    public String name;
+
+    /**
      * The width of the display in its natural orientation, in pixels.
      * This value is not affected by display rotation.
      */
@@ -38,6 +44,7 @@
     public float yDpi;
 
     public void copyFrom(DisplayDeviceInfo other) {
+        name = other.name;
         width = other.width;
         height = other.height;
         refreshRate = other.refreshRate;
@@ -46,9 +53,10 @@
         yDpi = other.yDpi;
     }
 
+    // For debugging purposes
     @Override
     public String toString() {
-        return width + " x " + height + ", " + refreshRate + " fps, "
+        return "\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, "
                 + "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi";
     }
 }
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index 468bf21..2ebad1d 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -19,11 +19,10 @@
 import android.Manifest;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
 import android.hardware.display.IDisplayManager;
 import android.os.Binder;
 import android.os.SystemProperties;
-import android.util.Slog;
-import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
@@ -47,41 +46,27 @@
 
     private final Object mLock = new Object();
 
-    private Context mContext;
+    private final Context mContext;
     private final boolean mHeadless;
 
-    private int mDisplayIdSeq = Display.DEFAULT_DISPLAY;
-
-    /** All registered DisplayAdapters. */
     private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
+    private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
 
-    /** All the DisplayAdapters showing the given displayId. */
-    private final SparseArray<ArrayList<DisplayAdapter>> mLogicalToPhysicals =
-            new SparseArray<ArrayList<DisplayAdapter>>();
-
-    /** All the DisplayInfos in the system indexed by deviceId */
-    private final SparseArray<DisplayInfo> mDisplayInfos = new SparseArray<DisplayInfo>();
-
-    private final ArrayList<DisplayCallback> mCallbacks =
-            new ArrayList<DisplayManagerService.DisplayCallback>();
-
-    public DisplayManagerService() {
+    public DisplayManagerService(Context context) {
+        mContext = context;
         mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
+
         registerDefaultDisplayAdapter();
     }
 
     private void registerDefaultDisplayAdapter() {
         if (mHeadless) {
-            registerDisplayAdapter(new HeadlessDisplayAdapter());
+            registerDisplayAdapter(new HeadlessDisplayAdapter(mContext));
         } else {
-            registerDisplayAdapter(new SurfaceFlingerDisplayAdapter());
+            registerDisplayAdapter(new SurfaceFlingerDisplayAdapter(mContext));
         }
     }
 
-    public void setContext(Context context) {
-        mContext = context;
-    }
-
     // FIXME: this isn't the right API for the long term
     public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) {
         // hardcoded assuming 720p touch screen plugged into HDMI and USB
@@ -90,6 +75,11 @@
         info.height = 720;
     }
 
+    /**
+     * Returns true if the device is headless.
+     *
+     * @return True if the device is headless.
+     */
     public boolean isHeadless() {
         return mHeadless;
     }
@@ -101,12 +91,10 @@
      */
     public void setDisplayInfo(int displayId, DisplayInfo info) {
         synchronized (mLock) {
-            DisplayInfo localInfo = mDisplayInfos.get(displayId);
-            if (localInfo == null) {
-                localInfo = new DisplayInfo();
-                mDisplayInfos.put(displayId, localInfo);
+            if (displayId != Display.DEFAULT_DISPLAY) {
+                throw new UnsupportedOperationException();
             }
-            localInfo.copyFrom(info);
+            mDefaultDisplayInfo.copyFrom(info);
         }
     }
 
@@ -118,177 +106,32 @@
     @Override // Binder call
     public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) {
         synchronized (mLock) {
-            DisplayInfo localInfo = mDisplayInfos.get(displayId);
-            if (localInfo == null) {
+            if (displayId != Display.DEFAULT_DISPLAY) {
                 return false;
             }
-            outInfo.copyFrom(localInfo);
+            outInfo.copyFrom(mDefaultDisplayInfo);
             return true;
         }
     }
 
-    /**
-     * Inform the service of a new physical display. A new logical displayId is created and the new
-     * physical display is immediately bound to it. Use removeAdapterFromDisplay to disconnect it.
-     *
-     * @param adapter The wrapper for information associated with the physical display.
-     */
-    public void registerDisplayAdapter(DisplayAdapter adapter) {
-
-        int displayId;
-        DisplayCallback[] callbacks;
-
-        synchronized (mLock) {
-            displayId = mDisplayIdSeq;
-            do {
-                // Find the next unused displayId. (Pretend like it might ever wrap around).
-                mDisplayIdSeq++;
-                if (mDisplayIdSeq < 0) {
-                    mDisplayIdSeq = Display.DEFAULT_DISPLAY + 1;
-                }
-            } while (mDisplayInfos.get(mDisplayIdSeq) != null);
-
-            adapter.setDisplayId(displayId);
-
-            createDisplayInfoLocked(displayId, adapter);
-
-            ArrayList<DisplayAdapter> list = new ArrayList<DisplayAdapter>();
-            list.add(adapter);
-            mLogicalToPhysicals.put(displayId, list);
-
-            mDisplayAdapters.add(adapter);
-            callbacks = mCallbacks.toArray(new DisplayCallback[mCallbacks.size()]);
-        }
-
-        for (int i = callbacks.length - 1; i >= 0; i--) {
-            callbacks[i].displayAdded(displayId);
-        }
-
-        // TODO: Notify SurfaceFlinger of new addition.
-    }
-
-    /**
-     * Connect a logical display to a physical display. Will remove the physical display from any
-     * logical display it is currently attached to.
-     *
-     * @param displayId The logical display. Will be created if it does not already exist.
-     * @param adapter The physical display.
-     */
-    public void addAdapterToDisplay(int displayId, DisplayAdapter adapter) {
-        if (adapter == null) {
-            // TODO: Or throw NPE?
-            Slog.e(TAG, "addDeviceToDisplay: Attempt to add null adapter");
-            return;
-        }
-
-        synchronized (mLock) {
-            if (!mDisplayAdapters.contains(adapter)) {
-                // TOOD: Handle unregistered adapter with exception or return value.
-                Slog.e(TAG, "addDeviceToDisplay: Attempt to add an unregistered adapter");
-                return;
+    private void registerDisplayAdapter(DisplayAdapter adapter) {
+        mDisplayAdapters.add(adapter);
+        adapter.register(new DisplayAdapter.Listener() {
+            @Override
+            public void onDisplayDeviceAdded(DisplayDevice device) {
+                DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+                device.getInfo(deviceInfo);
+                copyDisplayInfoFromDeviceInfo(mDefaultDisplayInfo, deviceInfo);
             }
 
-            DisplayInfo displayInfo = mDisplayInfos.get(displayId);
-            if (displayInfo == null) {
-                createDisplayInfoLocked(displayId, adapter);
+            @Override
+            public void onDisplayDeviceRemoved(DisplayDevice device) {
             }
-
-            Integer oldDisplayId = adapter.getDisplayId();
-            if (oldDisplayId != Display.NO_DISPLAY) {
-                if (oldDisplayId == displayId) {
-                    // adapter already added to displayId.
-                    return;
-                }
-
-                removeAdapterLocked(adapter);
-            }
-
-            ArrayList<DisplayAdapter> list = mLogicalToPhysicals.get(displayId);
-            if (list == null) {
-                list = new ArrayList<DisplayAdapter>();
-                mLogicalToPhysicals.put(displayId, list);
-            }
-            list.add(adapter);
-            adapter.setDisplayId(displayId);
-        }
-
-        // TODO: Notify SurfaceFlinger of new addition.
+        });
     }
 
-    /**
-     * Disconnect the physical display from whichever logical display it is attached to.
-     * @param adapter The physical display to detach.
-     */
-    public void removeAdapterFromDisplay(DisplayAdapter adapter) {
-        if (adapter == null) {
-            // TODO: Or throw NPE?
-            return;
-        }
-
-        synchronized (mLock) {
-            if (!mDisplayAdapters.contains(adapter)) {
-                // TOOD: Handle unregistered adapter with exception or return value.
-                Slog.e(TAG, "removeDeviceFromDisplay: Attempt to remove an unregistered adapter");
-                return;
-            }
-
-            removeAdapterLocked(adapter);
-        }
-
-        // TODO: Notify SurfaceFlinger of removal.
-    }
-
-    public void registerDisplayCallback(final DisplayCallback callback) {
-        synchronized (mLock) {
-            if (!mCallbacks.contains(callback)) {
-                mCallbacks.add(callback);
-            }
-        }
-    }
-
-    public void unregisterDisplayCallback(final DisplayCallback callback) {
-        synchronized (mLock) {
-            mCallbacks.remove(callback);
-        }
-    }
-
-    /**
-     * Create a new logical DisplayInfo and fill it in with information from the physical display.
-     * @param displayId The logical identifier.
-     * @param adapter The physical display for initial values.
-     */
-    private void createDisplayInfoLocked(int displayId, DisplayAdapter adapter) {
-        DisplayInfo displayInfo = new DisplayInfo();
-        DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
-        adapter.getDisplayDevice().getInfo(deviceInfo);
-        copyDisplayInfoFromDeviceInfo(displayInfo, deviceInfo);
-        mDisplayInfos.put(displayId, displayInfo);
-    }
-
-    /**
-     * Disconnect a physical display from its logical display. If there are no more physical
-     * displays attached to the logical display, delete the logical display.
-     * @param adapter The physical display to detach.
-     */
-    void removeAdapterLocked(DisplayAdapter adapter) {
-        int displayId = adapter.getDisplayId();
-        adapter.setDisplayId(Display.NO_DISPLAY);
-
-        ArrayList<DisplayAdapter> list = mLogicalToPhysicals.get(displayId);
-        if (list != null) {
-            list.remove(adapter);
-            if (list.isEmpty()) {
-                mLogicalToPhysicals.remove(displayId);
-                // TODO: Keep count of Windows attached to logical display and don't delete if
-                // there are any outstanding. Also, what keeps the WindowManager from continuing
-                // to use the logical display?
-                mDisplayInfos.remove(displayId);
-            }
-        }
-    }
-
-    private void copyDisplayInfoFromDeviceInfo(DisplayInfo displayInfo,
-                                               DisplayDeviceInfo deviceInfo) {
+    private void copyDisplayInfoFromDeviceInfo(
+            DisplayInfo displayInfo, DisplayDeviceInfo deviceInfo) {
         // Bootstrap the logical display using the physical display.
         displayInfo.appWidth = deviceInfo.width;
         displayInfo.appHeight = deviceInfo.height;
@@ -319,19 +162,15 @@
 
         pw.println("Headless: " + mHeadless);
 
-        DisplayDeviceInfo info = new DisplayDeviceInfo();
-        for (DisplayAdapter adapter : mDisplayAdapters) {
-            pw.println("Display for adapter " + adapter.getName()
-                + " assigned to Display " + adapter.getDisplayId());
-            DisplayDevice device = adapter.getDisplayDevice();
-            pw.print("  ");
-            device.getInfo(info);
-            pw.println(info);
-        }
-    }
+        synchronized (mLock) {
+            for (DisplayAdapter adapter : mDisplayAdapters) {
+                pw.println("Adapter: " + adapter.getName());
+            }
 
-    public interface DisplayCallback {
-        public void displayAdded(int displayId);
-        public void displayRemoved(int displayId);
+            pw.println("Default display info: " + mDefaultDisplayInfo);
+        }
+
+        pw.println("Default display: "
+                + DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY));
     }
 }
diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
index 3eaf40f..17c2360 100644
--- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java
+++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
@@ -16,23 +16,20 @@
 
 package com.android.server.display;
 
+import android.content.Context;
 import android.util.DisplayMetrics;
 
 /**
  * Provides a fake default display for headless systems.
  */
 public final class HeadlessDisplayAdapter extends DisplayAdapter {
-    private final DisplayDevice mDefaultDisplay = new DisplayDevice() {
-        @Override
-        public void getInfo(DisplayDeviceInfo outInfo) {
-            outInfo.width = 640;
-            outInfo.height = 480;
-            outInfo.refreshRate = 60;
-            outInfo.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
-            outInfo.xDpi = 160;
-            outInfo.yDpi = 160;
-        }
-    };
+    private final Context mContext;
+    private final HeadlessDisplayDevice mDefaultDisplayDevice;
+
+    public HeadlessDisplayAdapter(Context context) {
+        mContext = context;
+        mDefaultDisplayDevice = new HeadlessDisplayDevice();
+    }
 
     @Override
     public String getName() {
@@ -40,7 +37,26 @@
     }
 
     @Override
-    public DisplayDevice getDisplayDevice() {
-        return mDefaultDisplay;
+    public void register(Listener listener) {
+        listener.onDisplayDeviceAdded(mDefaultDisplayDevice);
+    }
+
+    private final class HeadlessDisplayDevice extends DisplayDevice {
+        @Override
+        public DisplayAdapter getAdapter() {
+            return HeadlessDisplayAdapter.this;
+        }
+
+        @Override
+        public void getInfo(DisplayDeviceInfo outInfo) {
+            outInfo.name = mContext.getResources().getString(
+                    com.android.internal.R.string.display_manager_built_in_display);
+            outInfo.width = 640;
+            outInfo.height = 480;
+            outInfo.refreshRate = 60;
+            outInfo.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
+            outInfo.xDpi = 160;
+            outInfo.yDpi = 160;
+        }
     }
 }
diff --git a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
index 539f7c1..9531acb 100644
--- a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
+++ b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
@@ -16,18 +16,21 @@
 
 package com.android.server.display;
 
+import android.content.Context;
+
 /**
  * A display adapter for the displays managed by Surface Flinger.
  */
 public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter {
+    private final Context mContext;
+    private final SurfaceFlingerDisplayDevice mDefaultDisplayDevice;
+
     private static native void nativeGetDefaultDisplayDeviceInfo(DisplayDeviceInfo outInfo);
 
-    private final DisplayDevice mDefaultDisplay = new DisplayDevice() {
-        @Override
-        public void getInfo(DisplayDeviceInfo outInfo) {
-            nativeGetDefaultDisplayDeviceInfo(outInfo);
-        }
-    };
+    public SurfaceFlingerDisplayAdapter(Context context) {
+        mContext = context;
+        mDefaultDisplayDevice = new SurfaceFlingerDisplayDevice();
+    }
 
     @Override
     public String getName() {
@@ -35,7 +38,21 @@
     }
 
     @Override
-    public DisplayDevice getDisplayDevice() {
-        return mDefaultDisplay;
+    public void register(Listener listener) {
+        listener.onDisplayDeviceAdded(mDefaultDisplayDevice);
+    }
+
+    private final class SurfaceFlingerDisplayDevice extends DisplayDevice {
+        @Override
+        public DisplayAdapter getAdapter() {
+            return SurfaceFlingerDisplayAdapter.this;
+        }
+
+        @Override
+        public void getInfo(DisplayDeviceInfo outInfo) {
+            outInfo.name = mContext.getResources().getString(
+                    com.android.internal.R.string.display_manager_built_in_display);
+            nativeGetDefaultDisplayDeviceInfo(outInfo);
+        }
     }
 }
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index 21100e2..0b8ff62 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -1218,8 +1218,12 @@
     }
 
     // Native callback.
-    private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
-        mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+    private void notifySwitch(long whenNanos, int switchCode, int switchValue) {
+        switch (switchCode) {
+            case SW_LID:
+                mCallbacks.notifyLidSwitchChanged(whenNanos, switchValue == 0);
+                break;
+        }
     }
 
     // Native callback.
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 48004bb..d4fe3fb 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -338,12 +338,14 @@
         return execute(builder.toString());
     }
 
-    public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath,
+    public int getSizeInfo(String pkgName, int persona, String apkPath, String fwdLockApkPath,
             String asecPath, PackageStats pStats) {
         StringBuilder builder = new StringBuilder("getsize");
         builder.append(' ');
         builder.append(pkgName);
         builder.append(' ');
+        builder.append(persona);
+        builder.append(' ');
         builder.append(apkPath);
         builder.append(' ');
         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 0d6e08d..a76f854 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -79,6 +79,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
 import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
 import android.net.Uri;
@@ -2422,6 +2423,9 @@
                 final int M = prefs.size();
                 for (int i=0; i<M; i++) {
                     final PreferredActivity pa = prefs.get(i);
+                    if (pa.mUserId != userId) {
+                        continue;
+                    }
                     if (pa.mPref.mMatch != match) {
                         continue;
                     }
@@ -5348,7 +5352,17 @@
     public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
             int flags, String installerPackageName, Uri verificationURI,
             ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
+        VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
+                manifestDigest);
+        installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+                installerPackageName, verificationParams, encryptionParams);
+    }
+
+    public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
+                null);
 
         final int uid = Binder.getCallingUid();
 
@@ -5365,7 +5379,7 @@
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
-                verificationURI, manifestDigest, encryptionParams);
+                verificationParams, encryptionParams);
         mHandler.sendMessage(msg);
     }
 
@@ -5729,7 +5743,7 @@
         @Override
         void handleStartCopy() throws RemoteException {
             synchronized (mInstallLock) {
-                mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats);
+                mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
             }
 
             final boolean mounted;
@@ -5795,8 +5809,7 @@
 
         private final Uri mPackageURI;
         final String installerPackageName;
-        final Uri verificationURI;
-        final ManifestDigest manifestDigest;
+        final VerificationParams verificationParams;
         private InstallArgs mArgs;
         private int mRet;
         private File mTempPackage;
@@ -5804,17 +5817,23 @@
 
         InstallParams(Uri packageURI,
                 IPackageInstallObserver observer, int flags,
-                String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest,
+                String installerPackageName, VerificationParams verificationParams,
                 ContainerEncryptionParams encryptionParams) {
             this.mPackageURI = packageURI;
             this.flags = flags;
             this.observer = observer;
             this.installerPackageName = installerPackageName;
-            this.verificationURI = verificationURI;
-            this.manifestDigest = manifestDigest;
+            this.verificationParams = verificationParams;
             this.encryptionParams = encryptionParams;
         }
 
+        public ManifestDigest getManifestDigest() {
+            if (verificationParams == null) {
+                return null;
+            }
+            return verificationParams.getManifestDigest();
+        }
+
         private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
             String packageName = pkgLite.packageName;
             int installLocation = pkgLite.installLocation;
@@ -6003,9 +6022,19 @@
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
 
-                    if (verificationURI != null) {
-                        verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
-                                verificationURI);
+                    if (verificationParams != null) {
+                        if (verificationParams.getVerificationURI() != null) {
+                           verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
+                                 verificationParams.getVerificationURI());
+                        }
+                        if (verificationParams.getOriginatingURI() != null) {
+                            verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
+                                  verificationParams.getOriginatingURI());
+                        }
+                        if (verificationParams.getReferrer() != null) {
+                            verification.putExtra(Intent.EXTRA_REFERRER,
+                                  verificationParams.getReferrer());
+                        }
                     }
 
                     final PackageVerificationState verificationState = new PackageVerificationState(
@@ -6341,7 +6370,7 @@
 
         FileInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.flags,
-                    params.installerPackageName, params.manifestDigest);
+                    params.installerPackageName, params.getManifestDigest());
         }
 
         FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
@@ -6628,7 +6657,7 @@
 
         AsecInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.flags,
-                    params.installerPackageName, params.manifestDigest);
+                    params.installerPackageName, params.getManifestDigest());
         }
 
         AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
@@ -7645,7 +7674,7 @@
                             mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
                         }
                     }
-                    clearPackagePreferredActivitiesLPw(deletedPs.name);
+                    clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
                 }
             }
             // can downgrade to reader
@@ -8007,12 +8036,12 @@
         return true;
     }
 
-    public void getPackageSizeInfo(final String packageName,
+    public void getPackageSizeInfo(final String packageName, int userHandle,
             final IPackageStatsObserver observer) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.GET_PACKAGE_SIZE, null);
 
-        PackageStats stats = new PackageStats(packageName);
+        PackageStats stats = new PackageStats(packageName, userHandle);
 
         /*
          * Queue up an async operation since the package measurement may take a
@@ -8023,7 +8052,8 @@
         mHandler.sendMessage(msg);
     }
 
-    private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
+    private boolean getPackageSizeInfoLI(String packageName, int userHandle,
+            PackageStats pStats) {
         if (packageName == null) {
             Slog.w(TAG, "Attempt to get size of null packageName.");
             return false;
@@ -8060,7 +8090,7 @@
                 publicSrcDir = applicationInfo.publicSourceDir;
             }
         }
-        int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
+        int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, publicSrcDir,
                 asecPath, pStats);
         if (res < 0) {
             return false;
@@ -8112,26 +8142,28 @@
     }
     
     public void addPreferredActivity(IntentFilter filter, int match,
-            ComponentName[] set, ComponentName activity) {
+            ComponentName[] set, ComponentName activity, int userId) {
         // writer
+        int callingUid = Binder.getCallingUid();
+        checkValidCaller(callingUid, userId);
         synchronized (mPackages) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
                     != PackageManager.PERMISSION_GRANTED) {
-                if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
+                if (getUidTargetSdkVersionLockedLPr(callingUid)
                         < Build.VERSION_CODES.FROYO) {
                     Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
-                            + Binder.getCallingUid());
+                            + callingUid);
                     return;
                 }
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
             }
-            
-            Slog.i(TAG, "Adding preferred activity " + activity + ":");
+
+            Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :");
             filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
             mSettings.mPreferredActivities.addFilter(
-                    new PreferredActivity(filter, match, set, activity));
+                    new PreferredActivity(filter, match, set, activity, userId));
             scheduleWriteSettingsLocked();            
         }
     }
@@ -8167,13 +8199,15 @@
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
             }
-            
+
+            final int callingUserId = UserHandle.getCallingUserId();
             ArrayList<PreferredActivity> removed = null;
             Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
             String action = filter.getAction(0);
             String category = filter.getCategory(0);
             while (it.hasNext()) {
                 PreferredActivity pa = it.next();
+                if (pa.mUserId != callingUserId) continue;
                 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
                     if (removed == null) {
                         removed = new ArrayList<PreferredActivity>();
@@ -8189,7 +8223,7 @@
                     mSettings.mPreferredActivities.removeFilter(pa);
                 }
             }
-            addPreferredActivity(filter, match, set, activity);
+            addPreferredActivity(filter, match, set, activity, callingUserId);
         }
     }
 
@@ -8213,17 +8247,21 @@
                 }
             }
 
-            if (clearPackagePreferredActivitiesLPw(packageName)) {
+            if (clearPackagePreferredActivitiesLPw(packageName, UserHandle.getCallingUserId())) {
                 scheduleWriteSettingsLocked();            
             }
         }
     }
 
-    boolean clearPackagePreferredActivitiesLPw(String packageName) {
+    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+    boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) {
         ArrayList<PreferredActivity> removed = null;
         Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
         while (it.hasNext()) {
             PreferredActivity pa = it.next();
+            if (userId != UserHandle.USER_ALL && pa.mUserId != userId) {
+                continue;
+            }
             if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
                 if (removed == null) {
                     removed = new ArrayList<PreferredActivity>();
@@ -8245,11 +8283,15 @@
             List<ComponentName> outActivities, String packageName) {
 
         int num = 0;
+        final int userId = UserHandle.getCallingUserId();
         // reader
         synchronized (mPackages) {
             final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
             while (it.hasNext()) {
                 final PreferredActivity pa = it.next();
+                if (pa.mUserId != userId) {
+                    continue;
+                }
                 if (packageName == null
                         || pa.mPref.mComponent.getPackageName().equals(packageName)) {
                     if (outFilters != null) {
diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/java/com/android/server/pm/PreferredActivity.java
index b100eb1..5539e84 100644
--- a/services/java/com/android/server/pm/PreferredActivity.java
+++ b/services/java/com/android/server/pm/PreferredActivity.java
@@ -33,22 +33,38 @@
     private static final String TAG = "PreferredActivity";
 
     private static final boolean DEBUG_FILTERS = false;
+    static final String ATTR_USER_ID = "userId";
 
     final PreferredComponent mPref;
+    final int mUserId;
 
     PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
+        this(filter, match, set, activity, 0);
+    }
+
+    PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity,
+            int userId) {
         super(filter);
+        mUserId = userId;
         mPref = new PreferredComponent(this, match, set, activity);
     }
 
     PreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException {
+        String userIdString = parser.getAttributeValue(null, ATTR_USER_ID);
+        if (userIdString != null && userIdString.length() > 0) {
+            mUserId = Integer.parseInt(userIdString);
+        } else {
+            // Old format with no userId specified - assume primary user
+            mUserId = 0;
+        }
         mPref = new PreferredComponent(this, parser);
     }
 
     public void writeToXml(XmlSerializer serializer) throws IOException {
+        serializer.attribute(null, ATTR_USER_ID, Integer.toString(mUserId));
         mPref.writeToXml(serializer);
         serializer.startTag(null, "filter");
-        super.writeToXml(serializer);
+            super.writeToXml(serializer);
         serializer.endTag(null, "filter");
     }
 
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index a828864..c292bbc 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -506,6 +506,8 @@
             Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
             addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
             mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
+            mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_BOOT_COMPLETED),
+                    new UserHandle(userInfo.id));
         }
         return userInfo;
     }
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java
index f3183f8..cf12b20 100644
--- a/services/java/com/android/server/power/DisplayPowerController.java
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -27,6 +27,7 @@
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.hardware.SystemSensorManager;
+import android.hardware.display.DisplayManager;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Looper;
@@ -35,6 +36,7 @@
 import android.util.Slog;
 import android.util.Spline;
 import android.util.TimeUtils;
+import android.view.Display;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -73,8 +75,8 @@
     // If true, uses the electron beam on animation.
     // We might want to turn this off if we cannot get a guarantee that the screen
     // actually turns on and starts showing new content after the call to set the
-    // screen state returns.
-    private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = true;
+    // screen state returns.  Playing the animation can also be somewhat slow.
+    private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false;
 
     private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 300;
     private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 600;
@@ -98,15 +100,15 @@
 
     // Brightness animation ramp rate in brightness units per second.
     private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
-    private static final int BRIGHTNESS_RAMP_RATE_SLOW = 50;
+    private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
 
     // Filter time constant in milliseconds for computing a moving
     // average of light samples.  Different constants are used
     // to calculate the average light level when adapting to brighter or
     // dimmer environments.
     // This parameter only controls the filtering of light samples.
-    private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 500;
-    private static final long DIMMING_LIGHT_TIME_CONSTANT = 2000;
+    private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 600;
+    private static final long DIMMING_LIGHT_TIME_CONSTANT = 4000;
 
     // Stability requirements in milliseconds for accepting a new brightness
     // level.  This is used for debouncing the light sensor.  Different constants
@@ -428,7 +430,8 @@
 
     private void initialize() {
         final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR;
-        mPowerState = new DisplayPowerState(new ElectronBeam(),
+        Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
+        mPowerState = new DisplayPowerState(new ElectronBeam(display),
                 new PhotonicModulator(executor,
                         mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT),
                         mSuspendBlocker));
@@ -476,11 +479,13 @@
             if (mPowerRequest == null) {
                 mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
                 mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
+                mPendingWaitForNegativeProximityLocked = false;
                 mPendingRequestChangedLocked = false;
                 mustInitialize = true;
             } else if (mPendingRequestChangedLocked) {
                 mPowerRequest.copyFrom(mPendingRequestLocked);
                 mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
+                mPendingWaitForNegativeProximityLocked = false;
                 mPendingRequestChangedLocked = false;
                 mDisplayReadyLocked = false;
             }
@@ -493,24 +498,33 @@
             initialize();
         }
 
-        // Clear a request to wait for negative proximity if needed.
-        if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_OFF
-                || mProximity == PROXIMITY_NEGATIVE
-                || mProximitySensor == null) {
-            mWaitingForNegativeProximity = false;
-        }
-
-        // Turn on the proximity sensor if needed.
+        // Apply the proximity sensor.
         if (mProximitySensor != null) {
-            setProximitySensorEnabled(mPowerRequest.useProximitySensor
-                    || mWaitingForNegativeProximity);
-            if (mProximitySensorEnabled && mProximity == PROXIMITY_POSITIVE) {
-                mScreenOffBecauseOfProximity = true;
-                setScreenOn(false);
-            } else if (mScreenOffBecauseOfProximity) {
+            if (mPowerRequest.useProximitySensor
+                    && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+                setProximitySensorEnabled(true);
+                if (!mScreenOffBecauseOfProximity
+                        && mProximity == PROXIMITY_POSITIVE) {
+                    mScreenOffBecauseOfProximity = true;
+                    setScreenOn(false);
+                }
+            } else if (mWaitingForNegativeProximity
+                    && mScreenOffBecauseOfProximity
+                    && mProximity == PROXIMITY_POSITIVE
+                    && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+                setProximitySensorEnabled(true);
+            } else {
+                setProximitySensorEnabled(false);
+                mWaitingForNegativeProximity = false;
+            }
+            if (mScreenOffBecauseOfProximity
+                    && mProximity != PROXIMITY_POSITIVE) {
                 mScreenOffBecauseOfProximity = false;
+                setScreenOn(true);
                 sendOnProximityNegative();
             }
+        } else {
+            mWaitingForNegativeProximity = false;
         }
 
         // Turn on the light sensor if needed.
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
index 5472148..2d24249 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -33,7 +33,6 @@
 import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.SurfaceSession;
-import android.view.WindowManagerImpl;
 
 import java.io.PrintWriter;
 import java.nio.ByteBuffer;
@@ -68,6 +67,7 @@
     private boolean mPrepared;
     private boolean mWarmUp;
 
+    private final Display mDisplay;
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
     private int mDisplayLayerStack; // layer stack associated with primary display
     private int mDisplayRotation;
@@ -90,7 +90,8 @@
     private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8);
     private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8);
 
-    public ElectronBeam() {
+    public ElectronBeam(Display display) {
+        mDisplay = display;
     }
 
     /**
@@ -109,9 +110,8 @@
         mWarmUp = warmUp;
 
         // Get the display size and adjust it for rotation.
-        Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
-        display.getDisplayInfo(mDisplayInfo);
-        mDisplayLayerStack = display.getDisplayId();
+        mDisplay.getDisplayInfo(mDisplayInfo);
+        mDisplayLayerStack = mDisplay.getLayerStack();
         mDisplayRotation = mDisplayInfo.rotation;
         if (mDisplayRotation == Surface.ROTATION_90
                 || mDisplayRotation == Surface.ROTATION_270) {
diff --git a/services/java/com/android/server/usb/UsbDebuggingManager.java b/services/java/com/android/server/usb/UsbDebuggingManager.java
new file mode 100644
index 0000000..a3b45c7
--- /dev/null
+++ b/services/java/com/android/server/usb/UsbDebuggingManager.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2012 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 an
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.Base64;
+
+import java.lang.Thread;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+public class UsbDebuggingManager implements Runnable {
+    private static final String TAG = "UsbDebuggingManager";
+    private static final boolean DEBUG = false;
+
+    private final String ADBD_SOCKET = "adbd";
+    private final String ADB_DIRECTORY = "misc/adb";
+    private final String ADB_KEYS_FILE = "adb_keys";
+    private final int BUFFER_SIZE = 4096;
+
+    private final Context mContext;
+    private final Thread mThread;
+    private final Handler mHandler;
+    private final HandlerThread mHandlerThread;
+    private boolean mAdbEnabled = false;
+    private String mFingerprints;
+    private LocalSocket mSocket = null;
+    private OutputStream mOutputStream = null;
+
+    public UsbDebuggingManager(Context context) {
+        mThread = new Thread(this);
+        mHandlerThread = new HandlerThread("UsbDebuggingHandler");
+        mHandlerThread.start();
+        mHandler = new UsbDebuggingHandler(mHandlerThread.getLooper());
+        mContext = context;
+    }
+
+    private void listenToSocket() throws IOException {
+        try {
+            byte[] buffer = new byte[BUFFER_SIZE];
+            LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
+                                         LocalSocketAddress.Namespace.RESERVED);
+            InputStream inputStream = null;
+
+            mSocket = new LocalSocket();
+            mSocket.connect(address);
+
+            mOutputStream = mSocket.getOutputStream();
+            inputStream = mSocket.getInputStream();
+
+            while (true) {
+                int count = inputStream.read(buffer);
+                if (count < 0) {
+                    Slog.e(TAG, "got " + count + " reading");
+                    break;
+                }
+
+                if (buffer[0] == 'P' && buffer[1] == 'K') {
+                    String key = new String(Arrays.copyOfRange(buffer, 2, count));
+                    Slog.d(TAG, "Received public key: " + key);
+                    Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
+                    msg.obj = key;
+                    mHandler.sendMessage(msg);
+                }
+                else {
+                    Slog.e(TAG, "Wrong message: " + (new String(Arrays.copyOfRange(buffer, 0, 2))));
+                    break;
+                }
+            }
+        } catch (IOException ex) {
+            Slog.e(TAG, "Communication error: ", ex);
+            throw ex;
+        } finally {
+            closeSocket();
+        }
+    }
+
+    @Override
+    public void run() {
+        while (mAdbEnabled) {
+            try {
+                listenToSocket();
+            } catch (Exception e) {
+                /* Don't loop too fast if adbd dies, before init restarts it */
+                SystemClock.sleep(1000);
+            }
+        }
+    }
+
+    private void closeSocket() {
+        try {
+            mOutputStream.close();
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed closing output stream: " + e);
+        }
+
+        try {
+            mSocket.close();
+        } catch (IOException ex) {
+            Slog.e(TAG, "Failed closing socket: " + ex);
+        }
+    }
+
+    private void sendResponse(String msg) {
+        if (mOutputStream != null) {
+            try {
+                mOutputStream.write(msg.getBytes());
+            }
+            catch (IOException ex) {
+                Slog.e(TAG, "Failed to write response:", ex);
+            }
+        }
+    }
+
+    class UsbDebuggingHandler extends Handler {
+        private static final int MESSAGE_ADB_ENABLED = 1;
+        private static final int MESSAGE_ADB_DISABLED = 2;
+        private static final int MESSAGE_ADB_ALLOW = 3;
+        private static final int MESSAGE_ADB_DENY = 4;
+        private static final int MESSAGE_ADB_CONFIRM = 5;
+
+        public UsbDebuggingHandler(Looper looper) {
+            super(looper);
+        }
+
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_ADB_ENABLED:
+                    if (mAdbEnabled)
+                        break;
+
+                    mAdbEnabled = true;
+
+                    mThread.start();
+
+                    break;
+
+                case MESSAGE_ADB_DISABLED:
+                    if (!mAdbEnabled)
+                        break;
+
+                    mAdbEnabled = false;
+                    closeSocket();
+
+                    try {
+                        mThread.join();
+                    } catch (Exception ex) {
+                    }
+
+                    mOutputStream = null;
+                    mSocket = null;
+
+                case MESSAGE_ADB_ALLOW: {
+                    String key = (String)msg.obj;
+                    String fingerprints = getFingerprints(key);
+
+                    if (!fingerprints.equals(mFingerprints)) {
+                        Slog.e(TAG, "Fingerprints do not match. Got "
+                                + fingerprints + ", expected " + mFingerprints);
+                        break;
+                    }
+
+                    if (msg.arg1 == 1) {
+                        writeKey(key);
+                    }
+
+                    sendResponse("OK");
+                    break;
+                }
+
+                case MESSAGE_ADB_DENY:
+                    sendResponse("NO");
+                    break;
+
+                case MESSAGE_ADB_CONFIRM: {
+                    String key = (String)msg.obj;
+                    mFingerprints = getFingerprints(key);
+                    showConfirmationDialog(key, mFingerprints);
+                    break;
+                }
+            }
+        }
+    }
+
+    private String getFingerprints(String key) {
+        String hex = "0123456789ABCDEF";
+        StringBuilder sb = new StringBuilder();
+        MessageDigest digester;
+
+        try {
+            digester = MessageDigest.getInstance("MD5");
+        } catch (Exception ex) {
+            Slog.e(TAG, "Error getting digester: " + ex);
+            return "";
+        }
+
+        byte[] base64_data = key.split("\\s+")[0].getBytes();
+        byte[] digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT));
+
+        for (int i = 0; i < digest.length; i++) {
+            sb.append(hex.charAt((digest[i] >> 4) & 0xf));
+            sb.append(hex.charAt(digest[i] & 0xf));
+            if (i < digest.length - 1)
+                sb.append(":");
+        }
+        return sb.toString();
+    }
+
+    private void showConfirmationDialog(String key, String fingerprints) {
+        Intent dialogIntent = new Intent();
+
+        dialogIntent.setClassName("com.android.systemui",
+                "com.android.systemui.usb.UsbDebuggingActivity");
+        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        dialogIntent.putExtra("key", key);
+        dialogIntent.putExtra("fingerprints", fingerprints);
+        try {
+            mContext.startActivity(dialogIntent);
+        } catch (ActivityNotFoundException e) {
+            Slog.e(TAG, "unable to start UsbDebuggingActivity");
+        }
+    }
+
+    private void writeKey(String key) {
+        File dataDir = Environment.getDataDirectory();
+        File adbDir = new File(dataDir, ADB_DIRECTORY);
+
+        if (!adbDir.exists()) {
+            Slog.e(TAG, "ADB data directory does not exist");
+            return;
+        }
+
+        try {
+            File keyFile = new File(adbDir, ADB_KEYS_FILE);
+
+            if (!keyFile.exists()) {
+                keyFile.createNewFile();
+                FileUtils.setPermissions(keyFile.toString(),
+                    FileUtils.S_IRUSR | FileUtils.S_IWUSR |
+                    FileUtils.S_IRGRP, -1, -1);
+            }
+
+            FileOutputStream fo = new FileOutputStream(keyFile, true);
+            fo.write(key.getBytes());
+            fo.write('\n');
+            fo.close();
+        }
+        catch (IOException ex) {
+            Slog.e(TAG, "Error writing key:" + ex);
+        }
+    }
+
+
+    public void setAdbEnabled(boolean enabled) {
+        mHandler.sendEmptyMessage(enabled ? UsbDebuggingHandler.MESSAGE_ADB_ENABLED
+                                          : UsbDebuggingHandler.MESSAGE_ADB_DISABLED);
+    }
+
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_ALLOW);
+        msg.arg1 = alwaysAllow ? 1 : 0;
+        msg.obj = publicKey;
+        mHandler.sendMessage(msg);
+    }
+
+    public void denyUsbDebugging() {
+        mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_DENY);
+    }
+
+
+    public void dump(FileDescriptor fd, PrintWriter pw) {
+        pw.println("  USB Debugging State:");
+        pw.println("    Connected to adbd: " + (mOutputStream != null));
+        pw.println("    Last key received: " + mFingerprints);
+        pw.println("    User keys:");
+        try {
+            pw.println(FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null));
+        } catch (IOException e) {
+            pw.println("IOException: " + e);
+        }
+        pw.println("    System keys:");
+        try {
+            pw.println(FileUtils.readTextFile(new File("/adb_keys"), 0, null));
+        } catch (IOException e) {
+            pw.println("IOException: " + e);
+        }
+    }
+}
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index a115345c..ddecf14 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -114,6 +114,7 @@
     private boolean mAudioSourceEnabled;
     private Map<String, List<Pair<String, String>>> mOemModeMap;
     private String[] mAccessoryStrings;
+    private UsbDebuggingManager mDebuggingManager;
 
     private class AdbSettingsObserver extends ContentObserver {
         public AdbSettingsObserver() {
@@ -166,6 +167,10 @@
             if (DEBUG) Slog.d(TAG, "accessory attached at boot");
             startAccessoryMode();
         }
+
+        if ("1".equals(SystemProperties.get("ro.adb.secure"))) {
+            mDebuggingManager = new UsbDebuggingManager(context);
+        }
     }
 
     public void systemReady() {
@@ -425,6 +430,9 @@
                 setEnabledFunctions(mDefaultFunctions, true);
                 updateAdbNotification();
             }
+            if (mDebuggingManager != null) {
+                mDebuggingManager.setAdbEnabled(mAdbEnabled);
+            }
         }
 
         private void setEnabledFunctions(String functions, boolean makeDefault) {
@@ -601,6 +609,9 @@
                     if (mCurrentAccessory != null) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
                     }
+                    if (mDebuggingManager != null) {
+                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
+                    }
                     break;
             }
         }
@@ -802,10 +813,25 @@
         return usbFunctions;
     }
 
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        if (mDebuggingManager != null) {
+            mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
+        }
+    }
+
+    public void denyUsbDebugging() {
+        if (mDebuggingManager != null) {
+            mDebuggingManager.denyUsbDebugging();
+        }
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw) {
         if (mHandler != null) {
             mHandler.dump(fd, pw);
         }
+        if (mDebuggingManager != null) {
+            mDebuggingManager.dump(fd, pw);
+        }
     }
 
     private native String[] nativeGetAccessoryStrings();
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 0205ef8..bebcd56 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -164,6 +164,16 @@
         }
     }
 
+    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
+    }
+
+    public void denyUsbDebugging() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+        mDeviceManager.denyUsbDebugging();
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 691e2aa..c25f010 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -47,7 +47,7 @@
     final Transformation thumbnailTransformation = new Transformation();
 
     /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
-    ArrayList<WindowStateAnimator> mAllAppWinAnimators;
+    ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
 
     static final Animation sDummyAnimation = new DummyAnimation();
 
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 142c60d..7d85d89 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -42,6 +42,7 @@
     static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
 
     final Context mContext;
+    final Display mDisplay;
     Surface mSurface;
     BlackFrame mCustomBlackFrame;
     BlackFrame mExitingBlackFrame;
@@ -186,9 +187,10 @@
                 pw.println();
     }
 
-    public ScreenRotationAnimation(Context context, SurfaceSession session,
+    public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
             boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
         mContext = context;
+        mDisplay = display;
 
         // Screenshot does NOT include rotation!
         if (originalRotation == Surface.ROTATION_90
@@ -213,13 +215,13 @@
         try {
             try {
                 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                    mSurface = new SurfaceTrace(session, 0, "FreezeSurface", Display.DEFAULT_DISPLAY,
-                        mWidth, mHeight,
-                        PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
+                    mSurface = new SurfaceTrace(session, 0, "FreezeSurface",
+                            mDisplay.getLayerStack(), mWidth, mHeight,
+                            PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
                 } else {
-                    mSurface = new Surface(session, 0, "FreezeSurface", Display.DEFAULT_DISPLAY,
-                        mWidth, mHeight,
-                        PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
+                    mSurface = new Surface(session, 0, "FreezeSurface",
+                            mDisplay.getLayerStack(), mWidth, mHeight,
+                            PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
                 }
                 if (!mSurface.isValid()) {
                     // Screenshot failed, punt.
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 4b072c3..775aa0f 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -22,8 +22,6 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.util.DisplayMetrics;
-import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceSession;
@@ -39,7 +37,7 @@
 
     public StrictModeFlash(Display display, SurfaceSession session) {
         try {
-            mSurface = new Surface(session, 0, "StrictModeFlash", Display.DEFAULT_DISPLAY,
+            mSurface = new Surface(session, 0, "StrictModeFlash", display.getLayerStack(),
                 1, 1, PixelFormat.TRANSLUCENT, 0);
         } catch (Surface.OutOfResourcesException e) {
             return;
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index 12076d8..5901cc8 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -35,6 +35,7 @@
  * Displays a watermark on top of the window manager's windows.
  */
 class Watermark {
+    final Display mDisplay;
     final String[] mTokens;
     final String mText;
     final Paint mTextPaint;
@@ -50,7 +51,7 @@
     int mLastDH;
     boolean mDrawNeeded;
 
-    Watermark(DisplayMetrics dm, SurfaceSession session, String[] tokens) {
+    Watermark(Display display, DisplayMetrics dm, SurfaceSession session, String[] tokens) {
         if (false) {
             Log.i(WindowManagerService.TAG, "*********************** WATERMARK");
             for (int i=0; i<tokens.length; i++) {
@@ -58,6 +59,7 @@
             }
         }
 
+        mDisplay = display;
         mTokens = tokens;
 
         StringBuilder builder = new StringBuilder(32);
@@ -112,7 +114,7 @@
 
         try {
             mSurface = new Surface(session, 0,
-                    "WatermarkSurface", Display.DEFAULT_DISPLAY,
+                    "WatermarkSurface", mDisplay.getLayerStack(),
                     1, 1, PixelFormat.TRANSLUCENT, 0);
             mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
             mSurface.setPosition(0, 0);
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 0dbe692..1defa49 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -190,8 +190,8 @@
             for (int i = 0; i < N; i++) {
                 final AppWindowAnimParams params = layoutToAnim.mAppWindowAnimParams.get(i);
                 AppWindowAnimator appAnimator = params.mAppAnimator;
-                appAnimator.mAllAppWinAnimators =
-                        new ArrayList<WindowStateAnimator>(params.mWinAnimators);
+                appAnimator.mAllAppWinAnimators.clear();
+                appAnimator.mAllAppWinAnimators.addAll(params.mWinAnimators);
                 mAppAnimators.add(appAnimator);
             }
         }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index c1884da..98adf38 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -127,7 +127,7 @@
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicy;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManagerPolicy.FakeWindow;
@@ -2141,7 +2141,7 @@
             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
             Rect outContentInsets, InputChannel outInputChannel) {
         int res = mPolicy.checkAddPermission(attrs);
-        if (res != WindowManagerImpl.ADD_OKAY) {
+        if (res != WindowManagerGlobal.ADD_OKAY) {
             return res;
         }
 
@@ -2157,7 +2157,7 @@
 
             if (mWindowMap.containsKey(client.asBinder())) {
                 Slog.w(TAG, "Window " + client + " is already added");
-                return WindowManagerImpl.ADD_DUPLICATE_ADD;
+                return WindowManagerGlobal.ADD_DUPLICATE_ADD;
             }
 
             if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
@@ -2165,13 +2165,13 @@
                 if (attachedWindow == null) {
                     Slog.w(TAG, "Attempted to add window with token that is not a window: "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                 }
                 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
                         && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
                     Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
                             + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                 }
             }
 
@@ -2182,22 +2182,22 @@
                         && attrs.type <= LAST_APPLICATION_WINDOW) {
                     Slog.w(TAG, "Attempted to add application window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 if (attrs.type == TYPE_INPUT_METHOD) {
                     Slog.w(TAG, "Attempted to add input method window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 if (attrs.type == TYPE_WALLPAPER) {
                     Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 if (attrs.type == TYPE_DREAM) {
                     Slog.w(TAG, "Attempted to add Dream window with unknown token "
                           + attrs.token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 token = new WindowToken(this, attrs.token, -1, false);
                 addToken = true;
@@ -2207,35 +2207,35 @@
                 if (atoken == null) {
                     Slog.w(TAG, "Attempted to add window with non-application token "
                           + token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_NOT_APP_TOKEN;
+                    return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
                 } else if (atoken.removed) {
                     Slog.w(TAG, "Attempted to add window with exiting application token "
                           + token + ".  Aborting.");
-                    return WindowManagerImpl.ADD_APP_EXITING;
+                    return WindowManagerGlobal.ADD_APP_EXITING;
                 }
                 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
                     // No need for this guy!
                     if (localLOGV) Slog.v(
                             TAG, "**** NO NEED TO START: " + attrs.getTitle());
-                    return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
+                    return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
                 }
             } else if (attrs.type == TYPE_INPUT_METHOD) {
                 if (token.windowType != TYPE_INPUT_METHOD) {
                     Slog.w(TAG, "Attempted to add input method window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
             } else if (attrs.type == TYPE_WALLPAPER) {
                 if (token.windowType != TYPE_WALLPAPER) {
                     Slog.w(TAG, "Attempted to add wallpaper window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
             } else if (attrs.type == TYPE_DREAM) {
                 if (token.windowType != TYPE_DREAM) {
                     Slog.w(TAG, "Attempted to add Dream window with bad token "
                             + attrs.token + ".  Aborting.");
-                      return WindowManagerImpl.ADD_BAD_APP_TOKEN;
+                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
             }
 
@@ -2247,13 +2247,13 @@
                 // continue.
                 Slog.w(TAG, "Adding window client " + client.asBinder()
                         + " that is dead, aborting.");
-                return WindowManagerImpl.ADD_APP_EXITING;
+                return WindowManagerGlobal.ADD_APP_EXITING;
             }
 
             mPolicy.adjustWindowParamsLw(win.mAttrs);
 
             res = mPolicy.prepareAddWindowLw(win, attrs);
-            if (res != WindowManagerImpl.ADD_OKAY) {
+            if (res != WindowManagerGlobal.ADD_OKAY) {
                 return res;
             }
 
@@ -2269,7 +2269,7 @@
 
             // From now on, no exceptions or errors allowed!
 
-            res = WindowManagerImpl.ADD_OKAY;
+            res = WindowManagerGlobal.ADD_OKAY;
 
             origId = Binder.clearCallingIdentity();
 
@@ -2313,10 +2313,10 @@
             mPolicy.getContentInsetHintLw(attrs, outContentInsets);
 
             if (mInTouchMode) {
-                res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
+                res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
             }
             if (win.mAppToken == null || !win.mAppToken.clientHidden) {
-                res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
+                res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
             }
 
             mInputMonitor.setUpdateInputWindowsNeededLw();
@@ -2748,7 +2748,7 @@
             }
 
             winAnimator.mSurfaceDestroyDeferred =
-                    (flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
+                    (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
 
             int attrChanges = 0;
             int flagChanges = 0;
@@ -2967,7 +2967,7 @@
             }
 
             mLayoutNeeded = true;
-            win.mGivenInsetsPending = (flags&WindowManagerImpl.RELAYOUT_INSETS_PENDING) != 0;
+            win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
             if (assignLayers) {
                 assignLayersLocked(win.getWindowList());
             }
@@ -3010,10 +3010,10 @@
 
         Binder.restoreCallingIdentity(origId);
 
-        return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0)
-                | (toBeDisplayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0)
-                | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0)
-                | (animating ? WindowManagerImpl.RELAYOUT_RES_ANIMATING : 0);
+        return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
+                | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
+                | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
+                | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
     }
 
     public void performDeferredDestroyWindow(Session session, IWindow client) {
@@ -5257,14 +5257,14 @@
 
     // Called by window manager policy.  Not exposed externally.
     @Override
-    public void shutdown() {
-        ShutdownThread.shutdown(mContext, true);
+    public void shutdown(boolean confirm) {
+        ShutdownThread.shutdown(mContext, confirm);
     }
 
     // Called by window manager policy.  Not exposed externally.
     @Override
-    public void rebootSafeMode() {
-        ShutdownThread.rebootSafeMode(mContext, true);
+    public void rebootSafeMode(boolean confirm) {
+        ShutdownThread.rebootSafeMode(mContext, confirm);
     }
 
     public void setInputFilter(IInputFilter filter) {
@@ -8367,15 +8367,23 @@
             NN = mOpeningApps.size();
             for (i=0; i<NN; i++) {
                 AppWindowToken wtoken = mOpeningApps.get(i);
+                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
-                wtoken.mAppAnimator.clearThumbnail();
+                appAnimator.clearThumbnail();
                 wtoken.reportedVisible = false;
                 wtoken.inPendingTransaction = false;
-                wtoken.mAppAnimator.animation = null;
+                appAnimator.animation = null;
                 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
                 wtoken.updateReportedVisibilityLocked();
                 wtoken.waitingToShow = false;
-                mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
+
+                appAnimator.mAllAppWinAnimators.clear();
+                final int N = wtoken.allAppWindows.size();
+                for (int j = 0; j < N; j++) {
+                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+                }
+                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+
                 if (animLp != null) {
                     int layer = -1;
                     for (int j=0; j<wtoken.windows.size(); j++) {
@@ -9629,7 +9637,7 @@
 
             // TODO(multidisplay): rotation on main screen only.
             DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo();
-            mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
+            mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, mDisplay,
                     mFxSession, inTransaction, displayInfo.logicalWidth, displayInfo.logicalHeight,
                     mDisplay.getRotation());
         }
@@ -9742,7 +9750,7 @@
             if (line != null) {
                 String[] toks = line.split("%");
                 if (toks != null && toks.length > 0) {
-                    mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks);
+                    mWatermark = new Watermark(mDisplay, mRealDisplayMetrics, mFxSession, toks);
                 }
             }
         } catch (FileNotFoundException e) {
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index d931426..899610f 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -474,24 +474,14 @@
         private final Point mSize = new Point();
         private final Rect mWindowCrop = new Rect();
         private boolean mShown = false;
-        private int mDisplayId;
-        private String mName = "Not named";
+        private int mLayerStack;
+        private String mName;
 
         public SurfaceTrace(SurfaceSession s,
-                       int pid, int displayId, int w, int h, int format, int flags) throws
-                       OutOfResourcesException {
-            super(s, pid, displayId, w, h, format, flags);
-            mSize.set(w, h);
-            mDisplayId = displayId;
-            Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
-                    + Debug.getCallers(3));
-        }
-
-        public SurfaceTrace(SurfaceSession s,
-                       int pid, String name, int displayId, int w, int h, int format, int flags)
+                       int pid, String name, int layerStack, int w, int h, int format, int flags)
                    throws OutOfResourcesException {
-            super(s, pid, name, displayId, w, h, format, flags);
-            mName = name;
+            super(s, pid, name, layerStack, w, h, format, flags);
+            mName = name != null ? name : "Not named";
             mSize.set(w, h);
             Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
                     + Debug.getCallers(3));
@@ -550,10 +540,10 @@
         }
 
         @Override
-        public void setDisplayId(int displayId) {
-            super.setDisplayId(displayId);
-            mDisplayId = displayId;
-            Slog.v(SURFACE_TAG, "setDisplayId: " + this + ". Called by " + Debug.getCallers(3));
+        public void setLayerStack(int layerStack) {
+            super.setLayerStack(layerStack);
+            mLayerStack = layerStack;
+            Slog.v(SURFACE_TAG, "setLayerStack: " + this + ". Called by " + Debug.getCallers(3));
         }
 
         @Override
@@ -597,7 +587,7 @@
         @Override
         public String toString() {
             return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
-                    + mName + " (" + mDisplayId + "): shown=" + mShown + " layer=" + mLayer
+                    + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
                     + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
                     + " " + mSize.x + "x" + mSize.y
                     + " crop=" + mWindowCrop.toShortString();
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index ca6f206..e6133af 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -42,6 +42,7 @@
     // members
     jfieldID mAcOnline;
     jfieldID mUsbOnline;
+    jfieldID mWirelessOnline;
     jfieldID mBatteryStatus;
     jfieldID mBatteryHealth;
     jfieldID mBatteryPresent;
@@ -71,6 +72,7 @@
 struct PowerSupplyPaths {
     char* acOnlinePath;
     char* usbOnlinePath;
+    char* wirelessOnlinePath;
     char* batteryStatusPath;
     char* batteryHealthPath;
     char* batteryPresentPath;
@@ -88,8 +90,8 @@
     switch (status[0]) {
         case 'C': return gConstants.statusCharging;         // Charging
         case 'D': return gConstants.statusDischarging;      // Discharging
-        case 'F': return gConstants.statusFull;             // Not charging
-        case 'N': return gConstants.statusNotCharging;      // Full
+        case 'F': return gConstants.statusFull;             // Full
+        case 'N': return gConstants.statusNotCharging;      // Not charging
         case 'U': return gConstants.statusUnknown;          // Unknown
             
         default: {
@@ -198,6 +200,7 @@
 {
     setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);
     setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline);
+    setBooleanField(env, obj, gPaths.wirelessOnlinePath, gFieldIds.mWirelessOnline);
     setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
     
     setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
@@ -260,6 +263,11 @@
                     if (access(path, R_OK) == 0)
                         gPaths.usbOnlinePath = strdup(path);
                 }
+                else if (strcmp(buf, "Wireless") == 0) {
+                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        gPaths.wirelessOnlinePath = strdup(path);
+                }
                 else if (strcmp(buf, "Battery") == 0) {
                     snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, name);
                     if (access(path, R_OK) == 0)
@@ -307,6 +315,8 @@
         ALOGE("acOnlinePath not found");
     if (!gPaths.usbOnlinePath)
         ALOGE("usbOnlinePath not found");
+    if (!gPaths.wirelessOnlinePath)
+        ALOGE("wirelessOnlinePath not found");
     if (!gPaths.batteryStatusPath)
         ALOGE("batteryStatusPath not found");
     if (!gPaths.batteryHealthPath)
@@ -331,6 +341,7 @@
     
     gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
     gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z");
+    gFieldIds.mWirelessOnline = env->GetFieldID(clazz, "mWirelessOnline", "Z");
     gFieldIds.mBatteryStatus = env->GetFieldID(clazz, "mBatteryStatus", "I");
     gFieldIds.mBatteryHealth = env->GetFieldID(clazz, "mBatteryHealth", "I");
     gFieldIds.mBatteryPresent = env->GetFieldID(clazz, "mBatteryPresent", "Z");
@@ -341,6 +352,7 @@
 
     LOG_FATAL_IF(gFieldIds.mAcOnline == NULL, "Unable to find BatteryService.AC_ONLINE_PATH");
     LOG_FATAL_IF(gFieldIds.mUsbOnline == NULL, "Unable to find BatteryService.USB_ONLINE_PATH");
+    LOG_FATAL_IF(gFieldIds.mWirelessOnline == NULL, "Unable to find BatteryService.WIRELESS_ONLINE_PATH");
     LOG_FATAL_IF(gFieldIds.mBatteryStatus == NULL, "Unable to find BatteryService.BATTERY_STATUS_PATH");
     LOG_FATAL_IF(gFieldIds.mBatteryHealth == NULL, "Unable to find BatteryService.BATTERY_HEALTH_PATH");
     LOG_FATAL_IF(gFieldIds.mBatteryPresent == NULL, "Unable to find BatteryService.BATTERY_PRESENT_PATH");
diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index 701b15a..495d4ab 100644
--- a/services/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/jni/com_android_server_input_InputManagerService.cpp
@@ -63,7 +63,7 @@
 static struct {
     jmethodID notifyConfigurationChanged;
     jmethodID notifyInputDevicesChanged;
-    jmethodID notifyLidSwitchChanged;
+    jmethodID notifySwitch;
     jmethodID notifyInputChannelBroken;
     jmethodID notifyANR;
     jmethodID filterInputEvent;
@@ -578,14 +578,9 @@
 
     JNIEnv* env = jniEnv();
 
-    switch (switchCode) {
-    case SW_LID:
-        // When switch value is set indicates lid is closed.
-        env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged,
-                when, switchValue == 0 /*lidOpen*/);
-        checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
-        break;
-    }
+    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch,
+            when, switchCode, switchValue);
+    checkAndClearExceptionFromCallback(env, "notifySwitch");
 }
 
 void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
@@ -1410,8 +1405,8 @@
     GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
             "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
 
-    GET_METHOD_ID(gServiceClassInfo.notifyLidSwitchChanged, clazz,
-            "notifyLidSwitchChanged", "(JZ)V");
+    GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz,
+            "notifySwitch", "(JII)V");
 
     GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
             "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 02d0b45..12ad4fea 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -39,6 +39,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
+import android.view.CompatibilityInfoHolder;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -487,4 +488,10 @@
     public boolean isRestricted() {
         throw new UnsupportedOperationException();        
     }
+
+    /** @hide */
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index ef14404..0fb51f0 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -39,6 +39,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -479,7 +480,8 @@
      * @hide - to match hiding in superclass
      */
     @Override
-    public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
+    public void getPackageSizeInfo(String packageName, int userHandle,
+            IPackageStatsObserver observer) {
         throw new UnsupportedOperationException();
     }
 
@@ -519,6 +521,16 @@
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void verifyPendingInstall(int id, int verificationCode) {
         throw new UnsupportedOperationException();
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
new file mode 100644
index 0000000..e7bfb4f
--- /dev/null
+++ b/tests/MemoryUsage/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := MemoryUsage
+
+LOCAL_SDK_VERSION := 7
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/tests/MemoryUsage/AndroidManifest.xml b/tests/MemoryUsage/AndroidManifest.xml
new file mode 100644
index 0000000..3932e5b
--- /dev/null
+++ b/tests/MemoryUsage/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.memoryusage">
+    <instrumentation android:label="Memory usage instrumentation"
+                     android:name="com.android.tests.memoryusage.MemoryUsageInstrumentation"
+                     android:targetPackage="com.android.tests.memoryusage" />
+
+    <application android:label="Memory Usage Test">
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java
new file mode 100644
index 0000000..ed6d7e6
--- /dev/null
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageInstrumentation.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 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 com.android.tests.memoryusage;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+
+/**
+ * InstrumentationTestRunner for use with the {@link MemoryUsageTest}.
+ */
+public class MemoryUsageInstrumentation extends InstrumentationTestRunner {
+
+    private Bundle arguments;
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        this.arguments = arguments;
+        super.onCreate(arguments);
+    }
+
+    public Bundle getBundle() {
+        return arguments;
+    }
+
+}
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
new file mode 100644
index 0000000..f26edc6
--- /dev/null
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2012 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 com.android.tests.memoryusage;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.Debug.MemoryInfo;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test is intended to measure the amount of memory applications use when
+ * they start. Names of the applications are passed in command line, and the
+ * test starts each application, waits until its memory usage is stabilized and
+ * reports the total PSS in kilobytes of each processes.
+ * The instrumentation expects the following key to be passed on the command line:
+ * apps - A list of applications to start and their corresponding result keys
+ * in the following format:
+ * -e apps <app name>^<result key>|<app name>^<result key>
+ */
+public class MemoryUsageTest extends InstrumentationTestCase {
+
+    private static final int SLEEP_TIME = 1000;
+    private static final int THRESHOLD = 1024;
+    private static final int MAX_ITERATIONS = 10;
+    private static final int MIN_ITERATIONS = 4;
+
+    private static final String TAG = "MemoryUsageInstrumentation";
+    private static final String KEY_APPS = "apps";
+
+    private Map<String, Intent> nameToIntent;
+    private Map<String, String> nameToProcess;
+    private Map<String, String> nameToResultKey;
+
+    public void testMemory() {
+        MemoryUsageInstrumentation instrumentation =
+                    (MemoryUsageInstrumentation) getInstrumentation();
+        Bundle args = instrumentation.getBundle();
+
+        createMappings();
+        parseArgs(args);
+
+        Bundle results = new Bundle();
+        for (String app : nameToResultKey.keySet()) {
+            String processName;
+            try {
+                processName = startApp(app);
+                measureMemory(app, processName, results);
+            } catch (NameNotFoundException e) {
+                Log.i(TAG, "Application " + app + " not found");
+            }
+
+        }
+        instrumentation.sendStatus(0, results);
+    }
+
+    private void parseArgs(Bundle args) {
+        nameToResultKey = new HashMap<String, String>();
+        String appList = args.getString(KEY_APPS);
+
+        if (appList == null)
+            return;
+
+        String appNames[] = appList.split("\\|");
+        for (String pair : appNames) {
+            String[] parts = pair.split("\\^");
+            if (parts.length != 2) {
+                Log.e(TAG, "The apps key is incorectly formatted");
+                fail();
+            }
+
+            nameToResultKey.put(parts[0], parts[1]);
+        }
+    }
+
+    private void createMappings() {
+        nameToIntent = new HashMap<String, Intent>();
+        nameToProcess = new HashMap<String, String>();
+
+        PackageManager pm = getInstrumentation().getContext()
+                .getPackageManager();
+        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+        intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+        List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+        if (ris == null || ris.isEmpty()) {
+            Log.i(TAG, "Could not find any apps");
+        } else {
+            for (ResolveInfo ri : ris) {
+                Log.i(TAG, "Name: " + ri.loadLabel(pm).toString()
+                        + " package: " + ri.activityInfo.packageName
+                        + " name: " + ri.activityInfo.name);
+                Intent startIntent = new Intent(intentToResolve);
+                startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                startIntent.setClassName(ri.activityInfo.packageName,
+                        ri.activityInfo.name);
+                nameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
+                nameToProcess.put(ri.loadLabel(pm).toString(),
+                        ri.activityInfo.processName);
+            }
+        }
+    }
+
+    private String startApp(String appName) throws NameNotFoundException {
+        Log.i(TAG, "Starting " + appName);
+
+        if (!nameToProcess.containsKey(appName))
+            throw new NameNotFoundException("Could not find: " + appName);
+
+        String process = nameToProcess.get(appName);
+        Intent startIntent = nameToIntent.get(appName);
+        getInstrumentation().getContext().startActivity(startIntent);
+        return process;
+    }
+
+    private void measureMemory(String appName, String processName,
+            Bundle results) {
+        List<Integer> pssData = new ArrayList<Integer>();
+        int pss = 0;
+        int iteration = 0;
+        while (iteration < MAX_ITERATIONS) {
+            sleep();
+            pss = getPss(processName);
+            Log.i(TAG, appName + "=" + pss);
+            if (pss < 0) {
+                reportError(appName, processName, results);
+                return;
+            }
+            pssData.add(pss);
+            if (iteration >= MIN_ITERATIONS && stabilized(pssData)) {
+                results.putInt(nameToResultKey.get(appName), pss);
+                return;
+            }
+            iteration++;
+        }
+
+        Log.w(TAG, appName + " memory usage did not stabilize");
+        results.putInt(appName, average(pssData));
+    }
+
+    private int average(List<Integer> pssData) {
+        int sum = 0;
+        for (int sample : pssData) {
+            sum += sample;
+        }
+
+        return sum / pssData.size();
+    }
+
+    private boolean stabilized(List<Integer> pssData) {
+        if (pssData.size() < 3)
+            return false;
+        int diff1 = Math.abs(pssData.get(pssData.size() - 1) - pssData.get(pssData.size() - 2));
+        int diff2 = Math.abs(pssData.get(pssData.size() - 2) - pssData.get(pssData.size() - 3));
+
+        Log.i(TAG, "diff1=" + diff1 + " diff2=" + diff2);
+
+        return (diff1 + diff2) < THRESHOLD;
+    }
+
+    private void sleep() {
+        try {
+            Thread.sleep(SLEEP_TIME);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
+    private void reportError(String appName, String processName, Bundle results) {
+        ActivityManager am = (ActivityManager) getInstrumentation()
+                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+        List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
+        if (crashes != null) {
+            for (ProcessErrorStateInfo crash : crashes) {
+                if (!crash.processName.equals(processName))
+                    continue;
+
+                Log.w(TAG, appName + " crashed: " + crash.shortMsg);
+                results.putString(nameToResultKey.get(appName), crash.shortMsg);
+                return;
+            }
+        }
+
+        results.putString(nameToResultKey.get(appName),
+                "Crashed for unknown reason");
+        Log.w(TAG, appName
+                + " not found in process list, most likely it is crashed");
+    }
+
+    private int getPss(String processName) {
+        ActivityManager am = (ActivityManager) getInstrumentation()
+                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
+        List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
+
+        for (RunningAppProcessInfo proc : apps) {
+            if (!proc.processName.equals(processName)) {
+                continue;
+            }
+
+            int[] pids = {
+                proc.pid };
+
+            MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0];
+            return meminfo.getTotalPss();
+
+        }
+        return -1;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
index 97d9969..4901f72b 100644
--- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -19,6 +19,7 @@
 import com.android.layoutlib.bridge.android.BridgeWindow;
 import com.android.layoutlib.bridge.android.BridgeWindowSession;
 
+import android.content.Context;
 import android.os.Handler;
 import android.view.View.AttachInfo;
 
@@ -28,8 +29,12 @@
 public class AttachInfo_Accessor {
 
     public static void setAttachInfo(View view) {
+        Context context = view.getContext();
+        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+        ViewRootImpl root = new ViewRootImpl(context, display);
         AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
-                new ViewRootImpl(view.getContext()), new Handler(), null);
+                display, root, new Handler(), null);
         info.mHasWindowFocus = true;
         info.mWindowVisibility = View.VISIBLE;
         info.mInTouchMode = false; // this is so that we can display selections.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 943357a..3d45bff 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -66,6 +66,7 @@
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.view.BridgeInflater;
+import android.view.CompatibilityInfoHolder;
 import android.view.Surface;
 import android.view.View;
 import android.view.ViewGroup;
@@ -1318,4 +1319,10 @@
         Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
         return null;
     }
+
+    @Override
+    public CompatibilityInfoHolder getCompatibilityInfo() {
+        // pass
+        return null;
+    }
 }
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 32261de..3e20756 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -47,19 +47,37 @@
     public int frequency;
 
     /**
+     * Time Synchronization Function (tsf) timestamp in microseconds when
+     * this result was last seen.
+     */
+     public long timestamp;
+
+    /**
      * We'd like to obtain the following attributes,
      * but they are not reported via the socket
      * interface, even though they are known
      * internally by wpa_supplicant.
      * {@hide}
      */
-    public ScanResult(String SSID, String BSSID, String caps, int level, int frequency) {
+    public ScanResult(String SSID, String BSSID, String caps, int level, int frequency, long tsf) {
         this.SSID = SSID;
         this.BSSID = BSSID;
         this.capabilities = caps;
         this.level = level;
         this.frequency = frequency;
-        //networkConfig = null;
+        this.timestamp = tsf;
+    }
+
+    /** copy constructor {@hide} */
+    public ScanResult(ScanResult source) {
+        if (source != null) {
+            SSID = source.SSID;
+            BSSID = source.BSSID;
+            capabilities = source.capabilities;
+            level = source.level;
+            frequency = source.frequency;
+            timestamp = source.timestamp;
+        }
     }
 
     @Override
@@ -76,7 +94,9 @@
             append(", level: ").
             append(level).
             append(", frequency: ").
-            append(frequency);
+            append(frequency).
+            append(", timestamp: ").
+            append(timestamp);
 
         return sb.toString();
     }
@@ -93,6 +113,7 @@
         dest.writeString(capabilities);
         dest.writeInt(level);
         dest.writeInt(frequency);
+        dest.writeLong(timestamp);
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -104,7 +125,8 @@
                     in.readString(),
                     in.readString(),
                     in.readInt(),
-                    in.readInt()
+                    in.readInt(),
+                    in.readLong()
                 );
             }
 
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 84c565b0..1b7e378 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -197,8 +197,22 @@
         return null;
     }
 
+    /**
+     * Format of results:
+     * =================
+     * bssid=68:7f:74:d7:1b:6e
+     * freq=2412
+     * level=-43
+     * tsf=1344621975160944
+     * age=2623
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zubyb
+     *
+     * RANGE=ALL gets all scan results
+     * MASK=<N> see wpa_supplicant/src/common/wpa_ctrl.h for details
+     */
     public String scanResults() {
-        return doStringCommand("SCAN_RESULTS");
+        return doStringCommand("BSS RANGE=ALL MASK=0x1986");
     }
 
     public boolean startDriver() {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 6abca65..1d06c76 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -114,7 +114,7 @@
     private final String mPrimaryDeviceType;
 
     /* Scan results handling */
-    private List<ScanResult> mScanResults;
+    private List<ScanResult> mScanResults = new ArrayList<ScanResult>();
     private static final Pattern scanResultPattern = Pattern.compile("\t+");
     private static final int SCAN_RESULT_CACHE_SIZE = 80;
     private final LruCache<String, ScanResult> mScanResultCache;
@@ -891,7 +891,13 @@
      * TODO: doc
      */
     public List<ScanResult> syncGetScanResultsList() {
-        return mScanResults;
+        synchronized (mScanResultCache) {
+            List<ScanResult> scanList = new ArrayList<ScanResult>();
+            for(ScanResult result: mScanResults) {
+                scanList.add(new ScanResult(result));
+            }
+            return scanList;
+        }
     }
 
     /**
@@ -1357,131 +1363,103 @@
         mContext.sendStickyBroadcast(intent);
     }
 
+    private static final String BSSID_STR = "bssid=";
+    private static final String FREQ_STR = "freq=";
+    private static final String LEVEL_STR = "level=";
+    private static final String TSF_STR = "tsf=";
+    private static final String FLAGS_STR = "flags=";
+    private static final String SSID_STR = "ssid=";
+    private static final String DELIMITER_STR = "====";
     /**
-     * Parse the scan result line passed to us by wpa_supplicant (helper).
-     * @param line the line to parse
-     * @return the {@link ScanResult} object
-     */
-    private ScanResult parseScanResult(String line) {
-        ScanResult scanResult = null;
-        if (line != null) {
-            /*
-             * Cache implementation (LinkedHashMap) is not synchronized, thus,
-             * must synchronized here!
-             */
-            synchronized (mScanResultCache) {
-                String[] result = scanResultPattern.split(line);
-                if (3 <= result.length && result.length <= 5) {
-                    String bssid = result[0];
-                    // bssid | frequency | level | flags | ssid
-                    int frequency;
-                    int level;
-                    try {
-                        frequency = Integer.parseInt(result[1]);
-                        level = Integer.parseInt(result[2]);
-                        /* some implementations avoid negative values by adding 256
-                         * so we need to adjust for that here.
-                         */
-                        if (level > 0) level -= 256;
-                    } catch (NumberFormatException e) {
-                        frequency = 0;
-                        level = 0;
-                    }
-
-                    /*
-                     * The formatting of the results returned by
-                     * wpa_supplicant is intended to make the fields
-                     * line up nicely when printed,
-                     * not to make them easy to parse. So we have to
-                     * apply some heuristics to figure out which field
-                     * is the SSID and which field is the flags.
-                     */
-                    String ssid;
-                    String flags;
-                    if (result.length == 4) {
-                        if (result[3].charAt(0) == '[') {
-                            flags = result[3];
-                            ssid = "";
-                        } else {
-                            flags = "";
-                            ssid = result[3];
-                        }
-                    } else if (result.length == 5) {
-                        flags = result[3];
-                        ssid = result[4];
-                    } else {
-                        // Here, we must have 3 fields: no flags and ssid
-                        // set
-                        flags = "";
-                        ssid = "";
-                    }
-
-                    // bssid + ssid is the hash key
-                    String key = bssid + ssid;
-                    scanResult = mScanResultCache.get(key);
-                    if (scanResult != null) {
-                        scanResult.level = level;
-                        scanResult.SSID = ssid;
-                        scanResult.capabilities = flags;
-                        scanResult.frequency = frequency;
-                    } else {
-                        // Do not add scan results that have no SSID set
-                        if (0 < ssid.trim().length()) {
-                            scanResult =
-                                new ScanResult(
-                                    ssid, bssid, flags, level, frequency);
-                            mScanResultCache.put(key, scanResult);
-                        }
-                    }
-                } else {
-                    loge("Misformatted scan result text with " +
-                          result.length + " fields: " + line);
-                }
-            }
-        }
-
-        return scanResult;
-    }
-
-    /**
-     * scanResults input format
-     * 00:bb:cc:dd:cc:ee       2427    166     [WPA-EAP-TKIP][WPA2-EAP-CCMP]   Net1
-     * 00:bb:cc:dd:cc:ff       2412    165     [WPA-EAP-TKIP][WPA2-EAP-CCMP]   Net2
+     * Format:
+     * bssid=68:7f:76:d7:1a:6e
+     * freq=2412
+     * level=-44
+     * tsf=1344626243700342
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zfdy
+     * ====
+     * bssid=68:5f:74:d7:1a:6f
+     * freq=5180
+     * level=-73
+     * tsf=1344626243700373
+     * flags=[WPA2-PSK-CCMP][WPS][ESS]
+     * ssid=zuby
+     * ====
      */
     private void setScanResults(String scanResults) {
+        String bssid = "";
+        int level = 0;
+        int freq = 0;
+        long tsf = 0;
+        String flags = "";
+        String ssid = "";
+
         if (scanResults == null) {
             return;
         }
 
-        List<ScanResult> scanList = new ArrayList<ScanResult>();
+        synchronized(mScanResultCache) {
+            mScanResults = new ArrayList<ScanResult>();
+            String[] lines = scanResults.split("\n");
 
-        int lineCount = 0;
-
-        int scanResultsLen = scanResults.length();
-        // Parse the result string, keeping in mind that the last line does
-        // not end with a newline.
-        for (int lineBeg = 0, lineEnd = 0; lineEnd <= scanResultsLen; ++lineEnd) {
-            if (lineEnd == scanResultsLen || scanResults.charAt(lineEnd) == '\n') {
-                ++lineCount;
-
-                if (lineCount == 1) {
-                    lineBeg = lineEnd + 1;
-                    continue;
-                }
-                if (lineEnd > lineBeg) {
-                    String line = scanResults.substring(lineBeg, lineEnd);
-                    ScanResult scanResult = parseScanResult(line);
-                    if (scanResult != null) {
-                        scanList.add(scanResult);
-                    } else {
-                        //TODO: hidden network handling
+            for (String line : lines) {
+                if (line.startsWith(BSSID_STR)) {
+                    bssid = line.substring(BSSID_STR.length());
+                } else if (line.startsWith(FREQ_STR)) {
+                    try {
+                        freq = Integer.parseInt(line.substring(FREQ_STR.length()));
+                    } catch (NumberFormatException e) {
+                        freq = 0;
                     }
+                } else if (line.startsWith(LEVEL_STR)) {
+                    try {
+                        level = Integer.parseInt(line.substring(LEVEL_STR.length()));
+                        /* some implementations avoid negative values by adding 256
+                         * so we need to adjust for that here.
+                         */
+                        if (level > 0) level -= 256;
+                    } catch(NumberFormatException e) {
+                        level = 0;
+                    }
+                } else if (line.startsWith(TSF_STR)) {
+                    try {
+                        tsf = Long.parseLong(line.substring(TSF_STR.length()));
+                    } catch (NumberFormatException e) {
+                        tsf = 0;
+                    }
+                } else if (line.startsWith(FLAGS_STR)) {
+                    flags = line.substring(FLAGS_STR.length());
+                } else if (line.startsWith(SSID_STR)) {
+                    ssid = line.substring(SSID_STR.length());
+                    if (ssid == null) ssid = "";
+                } else if (line.startsWith(DELIMITER_STR)) {
+                    if (bssid != null) {
+                        String key = bssid + ssid;
+                        ScanResult scanResult = mScanResultCache.get(key);
+                        if (scanResult != null) {
+                            scanResult.level = level;
+                            scanResult.SSID = ssid;
+                            scanResult.capabilities = flags;
+                            scanResult.frequency = freq;
+                            scanResult.timestamp = tsf;
+                        } else {
+                            scanResult =
+                                new ScanResult(
+                                        ssid, bssid, flags, level, freq, tsf);
+                            mScanResultCache.put(key, scanResult);
+                        }
+                        mScanResults.add(scanResult);
+                    }
+                    bssid = null;
+                    level = 0;
+                    freq = 0;
+                    tsf = 0;
+                    flags = "";
+                    ssid = "";
                 }
-                lineBeg = lineEnd + 1;
             }
         }
-
-        mScanResults = scanList;
     }
 
     /*
@@ -2828,7 +2806,7 @@
             if (DBG) log(getName() + "\n");
             mIsRunning = false;
             updateBatteryWorkSource(null);
-            mScanResults = null;
+            mScanResults = new ArrayList<ScanResult>();
 
             if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P);
             mContext.unregisterReceiver(mScreenReceiver);