Merge "Copy EXTRA_STREAM into ClipData and grant."
diff --git a/api/current.txt b/api/current.txt
index 20b0be6..8747e9a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2744,6 +2744,7 @@
     method public static boolean isUserAMonkey();
     method public void killBackgroundProcesses(java.lang.String);
     method public void moveTaskToFront(int, int);
+    method public void moveTaskToFront(int, int, android.os.Bundle);
     method public deprecated void restartPackage(java.lang.String);
     field public static final int MOVE_TASK_NO_USER_ACTION = 2; // 0x2
     field public static final int MOVE_TASK_WITH_HOME = 1; // 0x1
@@ -2867,9 +2868,14 @@
   public class ActivityOptions {
     method public void join(android.app.ActivityOptions);
     method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
+    method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int, android.app.ActivityOptions.OnAnimationStartedListener);
     method public android.os.Bundle toBundle();
   }
 
+  public static abstract interface ActivityOptions.OnAnimationStartedListener {
+    method public abstract void onAnimationStarted();
+  }
+
   public class AlarmManager {
     method public void cancel(android.app.PendingIntent);
     method public void set(int, long, android.app.PendingIntent);
@@ -5204,6 +5210,7 @@
     field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
     field public static final java.lang.String LOCATION_SERVICE = "location";
     field public static final int MODE_APPEND = 32768; // 0x8000
+    field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
     field public static final int MODE_MULTI_PROCESS = 4; // 0x4
     field public static final int MODE_PRIVATE = 0; // 0x0
     field public static final int MODE_WORLD_READABLE = 1; // 0x1
@@ -7334,6 +7341,7 @@
     method public deprecated boolean isDbLockedByOtherThreads();
     method public boolean isOpen();
     method public boolean isReadOnly();
+    method public boolean isWriteAheadLoggingEnabled();
     method public deprecated void markTableSyncable(java.lang.String, java.lang.String);
     method public deprecated void markTableSyncable(java.lang.String, java.lang.String, java.lang.String);
     method public boolean needUpgrade(int);
@@ -7356,6 +7364,7 @@
     method public static int releaseMemory();
     method public long replace(java.lang.String, java.lang.String, android.content.ContentValues);
     method public long replaceOrThrow(java.lang.String, java.lang.String, android.content.ContentValues) throws android.database.SQLException;
+    method public void setForeignKeyConstraintsEnabled(boolean);
     method public void setLocale(java.util.Locale);
     method public deprecated void setLockingEnabled(boolean);
     method public void setMaxSqlCacheSize(int);
@@ -7375,6 +7384,7 @@
     field public static final int CONFLICT_REPLACE = 5; // 0x5
     field public static final int CONFLICT_ROLLBACK = 1; // 0x1
     field public static final int CREATE_IF_NECESSARY = 268435456; // 0x10000000
+    field public static final int ENABLE_WRITE_AHEAD_LOGGING = 536870912; // 0x20000000
     field public static final int MAX_SQL_CACHE_SIZE = 100; // 0x64
     field public static final int NO_LOCALIZED_COLLATORS = 16; // 0x10
     field public static final int OPEN_READONLY = 1; // 0x1
@@ -7434,10 +7444,12 @@
     method public java.lang.String getDatabaseName();
     method public android.database.sqlite.SQLiteDatabase getReadableDatabase();
     method public android.database.sqlite.SQLiteDatabase getWritableDatabase();
+    method public void onConfigure(android.database.sqlite.SQLiteDatabase);
     method public abstract void onCreate(android.database.sqlite.SQLiteDatabase);
     method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
     method public void onOpen(android.database.sqlite.SQLiteDatabase);
     method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
+    method public void setWriteAheadLoggingEnabled(boolean);
   }
 
   public class SQLiteOutOfMemoryException extends android.database.sqlite.SQLiteException {
@@ -23177,6 +23189,7 @@
     method public void buildLayer();
     method public boolean callOnClick();
     method public boolean canResolveLayoutDirection();
+    method public boolean canResolveTextDirection();
     method public boolean canScrollHorizontally(int);
     method public boolean canScrollVertically(int);
     method public void cancelLongPress();
@@ -23568,7 +23581,6 @@
     method public boolean willNotCacheDrawing();
     method public boolean willNotDraw();
     field public static final android.util.Property ALPHA;
-    field protected static int DEFAULT_TEXT_DIRECTION;
     field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
     field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
     field public static final int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
@@ -23602,10 +23614,10 @@
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
     field public static final int LAYER_TYPE_NONE = 0; // 0x0
     field public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
-    field public static final int LAYOUT_DIRECTION_INHERIT = 4; // 0x4
-    field public static final int LAYOUT_DIRECTION_LOCALE = 8; // 0x8
-    field public static final int LAYOUT_DIRECTION_LTR = 1; // 0x1
-    field public static final int LAYOUT_DIRECTION_RTL = 2; // 0x2
+    field public static final int LAYOUT_DIRECTION_INHERIT = 2; // 0x2
+    field public static final int LAYOUT_DIRECTION_LOCALE = 3; // 0x3
+    field public static final int LAYOUT_DIRECTION_LTR = 0; // 0x0
+    field public static final int LAYOUT_DIRECTION_RTL = 1; // 0x1
     field public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; // 0x10
     field public static final int MEASURED_SIZE_MASK = 16777215; // 0xffffff
     field public static final int MEASURED_STATE_MASK = -16777216; // 0xff000000
@@ -23652,6 +23664,7 @@
     field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
     field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
     field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
+    field protected 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
diff --git a/build/jarjar-rules.txt b/build/jarjar-rules.txt
deleted file mode 100644
index 5fdb022..0000000
--- a/build/jarjar-rules.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-rule org.apache.commons com.android.internal.apache.commons
-
diff --git a/build/phone-hdpi-512-dalvik-heap.mk b/build/phone-hdpi-512-dalvik-heap.mk
deleted file mode 100644
index 16e0505..0000000
--- a/build/phone-hdpi-512-dalvik-heap.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Copyright (C) 2010 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.
-#
-
-# Provides overrides to configure the Dalvik heap for a standard high density
-# phone with around 512MB total RAM.
-
-PRODUCT_PROPERTY_OVERRIDES += \
-    dalvik.vm.heapstartsize=5m \
-    dalvik.vm.heapgrowthlimit=48m \
-    dalvik.vm.heapsize=128m
diff --git a/build/phone-hdpi-dalvik-heap.mk b/build/phone-hdpi-dalvik-heap.mk
deleted file mode 100644
index ab33b96..0000000
--- a/build/phone-hdpi-dalvik-heap.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright (C) 2010 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.
-#
-
-# Provides overrides to configure the Dalvik heap for a standard high density phone.
-
-PRODUCT_PROPERTY_OVERRIDES += \
-    dalvik.vm.heapstartsize=5m \
-    dalvik.vm.heapsize=32m
diff --git a/build/phone-xhdpi-1024-dalvik-heap.mk b/build/phone-xhdpi-1024-dalvik-heap.mk
deleted file mode 100644
index f76535a..0000000
--- a/build/phone-xhdpi-1024-dalvik-heap.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-
-# Provides overrides to configure the Dalvik heap for a standard tablet device.
-
-PRODUCT_PROPERTY_OVERRIDES += \
-    dalvik.vm.heapstartsize=8m \
-    dalvik.vm.heapgrowthlimit=64m \
-    dalvik.vm.heapsize=256m
diff --git a/build/tablet-dalvik-heap.mk b/build/tablet-dalvik-heap.mk
deleted file mode 100644
index 826a380..0000000
--- a/build/tablet-dalvik-heap.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2010 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.
-#
-
-# Provides overrides to configure the Dalvik heap for a standard tablet device.
-
-PRODUCT_PROPERTY_OVERRIDES += \
-    dalvik.vm.heapstartsize=5m \
-    dalvik.vm.heapgrowthlimit=48m \
-    dalvik.vm.heapsize=256m
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index c15c49f..53a0186 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -62,6 +62,7 @@
     private boolean mStopOption = false;
 
     private int mRepeat = 0;
+    private int mUserId = 0;
 
     private String mProfileFile;
 
@@ -135,7 +136,7 @@
             runToUri(false);
         } else if (op.equals("to-intent-uri")) {
             runToUri(true);
-        } else if (op.equals("switch-profile")) {
+        } else if (op.equals("switch-user")) {
             runSwitchUser();
         } else {
             throw new IllegalArgumentException("Unknown command: " + op);
@@ -152,6 +153,7 @@
         mStopOption = false;
         mRepeat = 0;
         mProfileFile = null;
+        mUserId = 0;
         Uri data = null;
         String type = null;
 
@@ -308,6 +310,8 @@
                 mStopOption = true;
             } else if (opt.equals("--opengl-trace")) {
                 mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
+            } else if (opt.equals("--user")) {
+                mUserId = Integer.parseInt(nextArgRequired());
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 showUsage();
@@ -407,7 +411,8 @@
                         System.err.println("Error: Package manager not running; aborting");
                         return;
                     }
-                    List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0);
+                    List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0,
+                            mUserId);
                     if (activities == null || activities.size() <= 0) {
                         System.err.println("Error: Intent does not match any activities: "
                                 + intent);
@@ -550,7 +555,7 @@
         IntentReceiver receiver = new IntentReceiver();
         System.out.println("Broadcasting: " + intent);
         mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false,
-                Binder.getOrigCallingUser());
+                mUserId);
         receiver.waitForFinish();
     }
 
@@ -1294,6 +1299,7 @@
                 "       am display-size [reset|MxN]\n" +
                 "       am to-uri [INTENT]\n" +
                 "       am to-intent-uri [INTENT]\n" +
+                "       am switch-user <USER_ID>\n" +
                 "\n" +
                 "am start: start an Activity.  Options are:\n" +
                 "    -D: enable debugging\n" +
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index ac5bffe..4d638d0 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -146,18 +146,18 @@
             return;
         }
 
-        if ("create-profile".equals(op)) {
-            runCreateProfile();
+        if ("create-user".equals(op)) {
+            runCreateUser();
             return;
         }
 
-        if ("remove-profile".equals(op)) {
-            runRemoveProfile();
+        if ("remove-user".equals(op)) {
+            runRemoveUser();
             return;
         }
 
-        if ("list-profiles".equals(op)) {
-            runListProfiles();
+        if ("list-users".equals(op)) {
+            runListUsers();
             return;
         }
 
@@ -215,6 +215,8 @@
             runListLibraries();
         } else if ("instrumentation".equals(type)) {
             runListInstrumentation();
+        } else if ("users".equals(type)) {
+            runListUsers();
         } else {
             System.err.println("Error: unknown list type '" + type + "'");
             showUsage();
@@ -832,10 +834,10 @@
         }
     }
 
-    public void runCreateProfile() {
+    public void runCreateUser() {
         // Need to be run as root
         if (Process.myUid() != ROOT_UID) {
-            System.err.println("Error: create-profile must be run as root");
+            System.err.println("Error: create-user must be run as root");
             return;
         }
         String name;
@@ -848,7 +850,7 @@
         name = arg;
         try {
             if (mPm.createUser(name, 0) == null) {
-                System.err.println("Error: couldn't create profile.");
+                System.err.println("Error: couldn't create User.");
                 showUsage();
             }
         } catch (RemoteException e) {
@@ -858,10 +860,10 @@
 
     }
 
-    public void runRemoveProfile() {
+    public void runRemoveUser() {
         // Need to be run as root
         if (Process.myUid() != ROOT_UID) {
-            System.err.println("Error: remove-profile must be run as root");
+            System.err.println("Error: remove-user must be run as root");
             return;
         }
         int userId;
@@ -880,7 +882,7 @@
         }
         try {
             if (!mPm.removeUser(userId)) {
-                System.err.println("Error: couldn't remove profile.");
+                System.err.println("Error: couldn't remove user.");
                 showUsage();
             }
         } catch (RemoteException e) {
@@ -889,10 +891,10 @@
         }
     }
 
-    public void runListProfiles() {
+    public void runListUsers() {
         // Need to be run as root
         if (Process.myUid() != ROOT_UID) {
-            System.err.println("Error: list-profiles must be run as root");
+            System.err.println("Error: list-users must be run as root");
             return;
         }
         try {
@@ -1029,7 +1031,29 @@
         return "unknown";
     }
 
+    private boolean isNumber(String s) {
+        try {
+            Integer.parseInt(s);
+        } catch (NumberFormatException nfe) {
+            return false;
+        }
+        return true;
+    }
+
     private void runSetEnabledSetting(int state) {
+        int userId = 0;
+        String option = nextOption();
+        if (option != null && option.equals("--user")) {
+            String optionData = nextOptionData();
+            if (optionData == null || !isNumber(optionData)) {
+                System.err.println("Error: no USER_ID specified");
+                showUsage();
+                return;
+            } else {
+                userId = Integer.parseInt(optionData);
+            }
+        }
+
         String pkg = nextArg();
         if (pkg == null) {
             System.err.println("Error: no package or component specified");
@@ -1039,20 +1063,20 @@
         ComponentName cn = ComponentName.unflattenFromString(pkg);
         if (cn == null) {
             try {
-                mPm.setApplicationEnabledSetting(pkg, state, 0);
+                mPm.setApplicationEnabledSetting(pkg, state, 0, userId);
                 System.err.println("Package " + pkg + " new state: "
                         + enabledSettingToString(
-                                mPm.getApplicationEnabledSetting(pkg)));
+                        mPm.getApplicationEnabledSetting(pkg, userId)));
             } catch (RemoteException e) {
                 System.err.println(e.toString());
                 System.err.println(PM_NOT_RUNNING_ERR);
             }
         } else {
             try {
-                mPm.setComponentEnabledSetting(cn, state, 0);
+                mPm.setComponentEnabledSetting(cn, state, 0, userId);
                 System.err.println("Component " + cn.toShortString() + " new state: "
                         + enabledSettingToString(
-                                mPm.getComponentEnabledSetting(cn)));
+                        mPm.getComponentEnabledSetting(cn, userId)));
             } catch (RemoteException e) {
                 System.err.println(e.toString());
                 System.err.println(PM_NOT_RUNNING_ERR);
@@ -1096,7 +1120,7 @@
      */
     private void displayPackageFilePath(String pckg) {
         try {
-            PackageInfo info = mPm.getPackageInfo(pckg, 0);
+            PackageInfo info = mPm.getPackageInfo(pckg, 0, 0);
             if (info != null && info.applicationInfo != null) {
                 System.out.print("package:");
                 System.out.println(info.applicationInfo.sourceDir);
@@ -1112,7 +1136,7 @@
         if (res != null) return res;
 
         try {
-            ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0);
+            ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0, 0);
             AssetManager am = new AssetManager();
             am.addAssetPath(ai.publicSourceDir);
             res = new Resources(am, null, null);
@@ -1178,19 +1202,20 @@
         System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
         System.err.println("       pm list features");
         System.err.println("       pm list libraries");
+        System.err.println("       pm list users");
         System.err.println("       pm path PACKAGE");
         System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
         System.err.println("       pm clear PACKAGE");
-        System.err.println("       pm enable PACKAGE_OR_COMPONENT");
-        System.err.println("       pm disable PACKAGE_OR_COMPONENT");
-        System.err.println("       pm disable-user PACKAGE_OR_COMPONENT");
+        System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
+        System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
+        System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm grant PACKAGE PERMISSION");
         System.err.println("       pm revoke PACKAGE PERMISSION");
         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
         System.err.println("       pm get-install-location");
-        System.err.println("       pm create-profile USER_NAME");
-        System.err.println("       pm remove-profile USER_ID");
+        System.err.println("       pm create-user USER_NAME");
+        System.err.println("       pm remove-user USER_ID");
         System.err.println("");
         System.err.println("pm list packages: prints all packages, optionally only");
         System.err.println("  those whose package name contains the text in FILTER.  Options:");
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index e47cdc0..64df5d1 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -176,8 +176,9 @@
                     }
 
                     onDrainThisBuffer(msg);
-                } else if (what == ACodec::kWhatEOS) {
-                    printf("$\n");
+                } else if (what == ACodec::kWhatEOS
+                        || what == ACodec::kWhatError) {
+                    printf((what == ACodec::kWhatEOS) ? "$\n" : "E\n");
 
                     int64_t delayUs = ALooper::GetNowUs() - mStartTimeUs;
 
@@ -412,7 +413,8 @@
         sp<AMessage> reply;
         CHECK(msg->findMessage("reply", &reply));
 
-        if (mSeekState == SEEK_FLUSHING) {
+        if (mSource == NULL || mSeekState == SEEK_FLUSHING) {
+            reply->setInt32("err", ERROR_END_OF_STREAM);
             reply->post();
             return;
         }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ea32745..b277efb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3639,7 +3639,7 @@
      */
     public void startActivityFromChild(Activity child, Intent intent,
             int requestCode) {
-        startActivityFromChild(child, intent, requestCode);
+        startActivityFromChild(child, intent, requestCode, null);
     }
 
     /**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d056b17..531a695 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -31,6 +31,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.Parcel;
@@ -816,6 +817,19 @@
     public static final int MOVE_TASK_NO_USER_ACTION = 0x00000002;
 
     /**
+     * Equivalent to calling {@link #moveTaskToFront(int, int, Bundle)}
+     * with a null options argument.
+     *
+     * @param taskId The identifier of the task to be moved, as found in
+     * {@link RunningTaskInfo} or {@link RecentTaskInfo}.
+     * @param flags Additional operational flags, 0 or more of
+     * {@link #MOVE_TASK_WITH_HOME}.
+     */
+    public void moveTaskToFront(int taskId, int flags) {
+        moveTaskToFront(taskId, flags, null);
+    }
+
+    /**
      * Ask that the task associated with a given task ID be moved to the
      * front of the stack, so it is now visible to the user.  Requires that
      * the caller hold permission {@link android.Manifest.permission#REORDER_TASKS}
@@ -825,10 +839,13 @@
      * {@link RunningTaskInfo} or {@link RecentTaskInfo}.
      * @param flags Additional operational flags, 0 or more of
      * {@link #MOVE_TASK_WITH_HOME}.
+     * @param options Additional options for the operation, either null or
+     * as per {@link Context#startActivity(Intent, android.os.Bundle)
+     * Context.startActivity(Intent, Bundle)}.
      */
-    public void moveTaskToFront(int taskId, int flags) {
+    public void moveTaskToFront(int taskId, int flags, Bundle options) {
         try {
-            ActivityManagerNative.getDefault().moveTaskToFront(taskId, flags);
+            ActivityManagerNative.getDefault().moveTaskToFront(taskId, flags, options);
         } catch (RemoteException e) {
             // System dead, we will be dead too soon!
         }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 22793c0..c402329 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -510,7 +510,9 @@
             data.enforceInterface(IActivityManager.descriptor);
             int task = data.readInt();
             int fl = data.readInt();
-            moveTaskToFront(task, fl);
+            Bundle options = data.readInt() != 0
+                    ? Bundle.CREATOR.createFromParcel(data) : null;
+            moveTaskToFront(task, fl, options);
             reply.writeNoException();
             return true;
         }
@@ -2143,13 +2145,19 @@
         reply.recycle();
         return list;
     }
-    public void moveTaskToFront(int task, int flags) throws RemoteException
+    public void moveTaskToFront(int task, int flags, Bundle options) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(task);
         data.writeInt(flags);
+        if (options != null) {
+            data.writeInt(1);
+            options.writeToParcel(data, 0);
+        } else {
+            data.writeInt(0);
+        }
         mRemote.transact(MOVE_TASK_TO_FRONT_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 03bc338..c637df0 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -17,7 +17,13 @@
 package android.app;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.IRemoteCallback;
+import android.os.Message;
+import android.os.RemoteException;
+import android.view.View;
 
 /**
  * Helper class for building an options Bundle that can be used with
@@ -32,6 +38,12 @@
     public static final String KEY_PACKAGE_NAME = "android:packageName";
 
     /**
+     * Type of animation that arguments specify.
+     * @hide
+     */
+    public static final String KEY_ANIM_TYPE = "android:animType";
+
+    /**
      * Custom enter animation resource ID.
      * @hide
      */
@@ -43,10 +55,45 @@
      */
     public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes";
 
+    /**
+     * Bitmap for thumbnail animation.
+     * @hide
+     */
+    public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail";
+
+    /**
+     * Start X position of thumbnail animation.
+     * @hide
+     */
+    public static final String KEY_ANIM_START_X = "android:animStartX";
+
+    /**
+     * Start Y position of thumbnail animation.
+     * @hide
+     */
+    public static final String KEY_ANIM_START_Y = "android:animStartY";
+
+    /**
+     * Callback for when animation is started.
+     * @hide
+     */
+    public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
+
+    /** @hide */
+    public static final int ANIM_NONE = 0;
+    /** @hide */
+    public static final int ANIM_CUSTOM = 1;
+    /** @hide */
+    public static final int ANIM_THUMBNAIL = 2;
+
     private String mPackageName;
-    private boolean mIsCustomAnimation;
+    private int mAnimationType = ANIM_NONE;
     private int mCustomEnterResId;
     private int mCustomExitResId;
+    private Bitmap mThumbnail;
+    private int mStartX;
+    private int mStartY;
+    private IRemoteCallback mAnimationStartedListener;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -65,22 +112,79 @@
             int enterResId, int exitResId) {
         ActivityOptions opts = new ActivityOptions();
         opts.mPackageName = context.getPackageName();
-        opts.mIsCustomAnimation = true;
+        opts.mAnimationType = ANIM_CUSTOM;
         opts.mCustomEnterResId = enterResId;
         opts.mCustomExitResId = exitResId;
         return opts;
     }
 
+    /**
+     * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
+     * to find out when the given animation has started running.
+     */
+    public interface OnAnimationStartedListener {
+        void onAnimationStarted();
+    }
+
+    /**
+     * Create an ActivityOptions specifying an animation where a thumbnail
+     * is scaled from a given position to the new activity window that is
+     * being started.
+     *
+     * @param source The View that this thumbnail is animating from.  This
+     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+     * @param thumbnail The bitmap that will be shown as the initial thumbnail
+     * of the animation.
+     * @param startX The x starting location of the bitmap, in screen coordiantes.
+     * @param startY The y starting location of the bitmap, in screen coordinates.
+     * @param listener Optional OnAnimationStartedListener to find out when the
+     * requested animation has started running.  If for some reason the animation
+     * is not executed, the callback will happen immediately.
+     * @return Returns a new ActivityOptions object that you can use to
+     * supply these options as the options Bundle when starting an activity.
+     */
+    public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
+            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+        ActivityOptions opts = new ActivityOptions();
+        opts.mPackageName = source.getContext().getPackageName();
+        opts.mAnimationType = ANIM_THUMBNAIL;
+        opts.mThumbnail = thumbnail;
+        int[] pts = new int[2];
+        source.getLocationOnScreen(pts);
+        opts.mStartX = pts[0] + startX;
+        opts.mStartY = pts[1] + startY;
+        if (listener != null) {
+            final Handler h = source.getHandler();
+            final OnAnimationStartedListener finalListener = listener;
+            opts.mAnimationStartedListener = new IRemoteCallback.Stub() {
+                @Override public void sendResult(Bundle data) throws RemoteException {
+                    h.post(new Runnable() {
+                        @Override public void run() {
+                            finalListener.onAnimationStarted();
+                        }
+                    });
+                }
+            };
+        }
+        return opts;
+    }
+
     private ActivityOptions() {
     }
 
     /** @hide */
     public ActivityOptions(Bundle opts) {
         mPackageName = opts.getString(KEY_PACKAGE_NAME);
-        if (opts.containsKey(KEY_ANIM_ENTER_RES_ID)) {
-            mIsCustomAnimation = true;
+        mAnimationType = opts.getInt(KEY_ANIM_TYPE);
+        if (mAnimationType == ANIM_CUSTOM) {
             mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
             mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
+        } else if (mAnimationType == ANIM_THUMBNAIL) {
+            mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
+            mStartX = opts.getInt(KEY_ANIM_START_X, 0);
+            mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
+            mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
+                    opts.getIBinder(KEY_ANIM_START_LISTENER));
         }
     }
 
@@ -90,8 +194,8 @@
     }
 
     /** @hide */
-    public boolean isCustomAnimation() {
-        return mIsCustomAnimation;
+    public int getAnimationType() {
+        return mAnimationType;
     }
 
     /** @hide */
@@ -104,6 +208,43 @@
         return mCustomExitResId;
     }
 
+    /** @hide */
+    public Bitmap getThumbnail() {
+        return mThumbnail;
+    }
+
+    /** @hide */
+    public int getStartX() {
+        return mStartX;
+    }
+
+    /** @hide */
+    public int getStartY() {
+        return mStartY;
+    }
+
+    /** @hide */
+    public IRemoteCallback getOnAnimationStartListener() {
+        return mAnimationStartedListener;
+    }
+
+    /** @hide */
+    public void abort() {
+        if (mAnimationStartedListener != null) {
+            try {
+                mAnimationStartedListener.sendResult(null);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /** @hide */
+    public static void abort(Bundle options) {
+        if (options != null) {
+            (new ActivityOptions(options)).abort();
+        }
+    }
+
     /**
      * Join the values in <var>otherOptions</var> in to this one.  Any values
      * defined in <var>otherOptions</var> replace those in the base options.
@@ -112,10 +253,27 @@
         if (otherOptions.mPackageName != null) {
             mPackageName = otherOptions.mPackageName;
         }
-        if (otherOptions.mIsCustomAnimation) {
-            mIsCustomAnimation = true;
-            mCustomEnterResId = otherOptions.mCustomEnterResId;
-            mCustomExitResId = otherOptions.mCustomExitResId;
+        switch (otherOptions.mAnimationType) {
+            case ANIM_CUSTOM:
+                mAnimationType = otherOptions.mAnimationType;
+                mCustomEnterResId = otherOptions.mCustomEnterResId;
+                mCustomExitResId = otherOptions.mCustomExitResId;
+                mThumbnail = null;
+                mAnimationStartedListener = null;
+                break;
+            case ANIM_THUMBNAIL:
+                mAnimationType = otherOptions.mAnimationType;
+                mThumbnail = otherOptions.mThumbnail;
+                mStartX = otherOptions.mStartX;
+                mStartY = otherOptions.mStartY;
+                if (otherOptions.mAnimationStartedListener != null) {
+                    try {
+                        otherOptions.mAnimationStartedListener.sendResult(null);
+                    } catch (RemoteException e) {
+                    }
+                }
+                mAnimationStartedListener = otherOptions.mAnimationStartedListener;
+                break;
         }
     }
 
@@ -132,9 +290,19 @@
         if (mPackageName != null) {
             b.putString(KEY_PACKAGE_NAME, mPackageName);
         }
-        if (mIsCustomAnimation) {
-            b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
-            b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
+        switch (mAnimationType) {
+            case ANIM_CUSTOM:
+                b.putInt(KEY_ANIM_TYPE, mAnimationType);
+                b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
+                b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
+                break;
+            case ANIM_THUMBNAIL:
+                b.putInt(KEY_ANIM_TYPE, mAnimationType);
+                b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
+                b.putInt(KEY_ANIM_START_X, mStartX);
+                b.putInt(KEY_ANIM_START_Y, mStartY);
+                b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
+                        != null ? mAnimationStartedListener.asBinder() : null);
         }
         return b;
     }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2a3e213..0860890 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1586,7 +1586,7 @@
         ApplicationInfo ai = null;
         try {
             ai = getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_SHARED_LIBRARY_FILES);
+                    PackageManager.GET_SHARED_LIBRARY_FILES, UserId.myUserId());
         } catch (RemoteException e) {
             // Ignore
         }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 758ce09..f38540c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -49,6 +49,7 @@
 import android.net.Uri;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserId;
 import android.util.Log;
 
 import java.lang.ref.WeakReference;
@@ -67,7 +68,7 @@
     public PackageInfo getPackageInfo(String packageName, int flags)
             throws NameNotFoundException {
         try {
-            PackageInfo pi = mPM.getPackageInfo(packageName, flags);
+            PackageInfo pi = mPM.getPackageInfo(packageName, flags, UserId.myUserId());
             if (pi != null) {
                 return pi;
             }
@@ -197,7 +198,7 @@
     public ApplicationInfo getApplicationInfo(String packageName, int flags)
             throws NameNotFoundException {
         try {
-            ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
+            ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, UserId.myUserId());
             if (ai != null) {
                 return ai;
             }
@@ -212,7 +213,7 @@
     public ActivityInfo getActivityInfo(ComponentName className, int flags)
             throws NameNotFoundException {
         try {
-            ActivityInfo ai = mPM.getActivityInfo(className, flags);
+            ActivityInfo ai = mPM.getActivityInfo(className, flags, UserId.myUserId());
             if (ai != null) {
                 return ai;
             }
@@ -227,7 +228,7 @@
     public ActivityInfo getReceiverInfo(ComponentName className, int flags)
             throws NameNotFoundException {
         try {
-            ActivityInfo ai = mPM.getReceiverInfo(className, flags);
+            ActivityInfo ai = mPM.getReceiverInfo(className, flags, UserId.myUserId());
             if (ai != null) {
                 return ai;
             }
@@ -242,7 +243,7 @@
     public ServiceInfo getServiceInfo(ComponentName className, int flags)
             throws NameNotFoundException {
         try {
-            ServiceInfo si = mPM.getServiceInfo(className, flags);
+            ServiceInfo si = mPM.getServiceInfo(className, flags, UserId.myUserId());
             if (si != null) {
                 return si;
             }
@@ -257,7 +258,7 @@
     public ProviderInfo getProviderInfo(ComponentName className, int flags)
             throws NameNotFoundException {
         try {
-            ProviderInfo pi = mPM.getProviderInfo(className, flags);
+            ProviderInfo pi = mPM.getProviderInfo(className, flags, UserId.myUserId());
             if (pi != null) {
                 return pi;
             }
@@ -422,6 +423,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public List<ApplicationInfo> getInstalledApplications(int flags) {
+        int userId = UserId.getUserId(Process.myUid());
         try {
             final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>();
             ApplicationInfo lastItem = null;
@@ -429,7 +431,7 @@
 
             do {
                 final String lastKey = lastItem != null ? lastItem.packageName : null;
-                slice = mPM.getInstalledApplications(flags, lastKey);
+                slice = mPM.getInstalledApplications(flags, lastKey, userId);
                 lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR);
             } while (!slice.isLastSlice());
 
@@ -445,7 +447,7 @@
             return mPM.resolveIntent(
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                flags);
+                    flags, UserId.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -458,7 +460,8 @@
             return mPM.queryIntentActivities(
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                flags);
+                flags,
+                UserId.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -490,7 +493,7 @@
         try {
             return mPM.queryIntentActivityOptions(caller, specifics,
                                                   specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
-                                                  flags);
+                                                  flags, UserId.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -502,7 +505,8 @@
             return mPM.queryIntentReceivers(
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                flags);
+                flags,
+                UserId.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -514,7 +518,8 @@
             return mPM.resolveService(
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                flags);
+                flags,
+                UserId.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -526,7 +531,8 @@
             return mPM.queryIntentServices(
                 intent,
                 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                flags);
+                flags,
+                UserId.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -536,7 +542,7 @@
     public ProviderInfo resolveContentProvider(String name,
                                                int flags) {
         try {
-            return mPM.resolveContentProvider(name, flags);
+            return mPM.resolveContentProvider(name, flags, UserId.myUserId());
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -1026,7 +1032,7 @@
     public void clearApplicationUserData(String packageName,
                                          IPackageDataObserver observer) {
         try {
-            mPM.clearApplicationUserData(packageName, observer);
+            mPM.clearApplicationUserData(packageName, observer, UserId.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1139,7 +1145,7 @@
     public void setComponentEnabledSetting(ComponentName componentName,
                                            int newState, int flags) {
         try {
-            mPM.setComponentEnabledSetting(componentName, newState, flags);
+            mPM.setComponentEnabledSetting(componentName, newState, flags, UserId.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1148,7 +1154,7 @@
     @Override
     public int getComponentEnabledSetting(ComponentName componentName) {
         try {
-            return mPM.getComponentEnabledSetting(componentName);
+            return mPM.getComponentEnabledSetting(componentName, UserId.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1159,7 +1165,7 @@
     public void setApplicationEnabledSetting(String packageName,
                                              int newState, int flags) {
         try {
-            mPM.setApplicationEnabledSetting(packageName, newState, flags);
+            mPM.setApplicationEnabledSetting(packageName, newState, flags, UserId.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
@@ -1168,7 +1174,7 @@
     @Override
     public int getApplicationEnabledSetting(String packageName) {
         try {
-            return mPM.getApplicationEnabledSetting(packageName);
+            return mPM.getApplicationEnabledSetting(packageName, UserId.myUserId());
         } catch (RemoteException e) {
             // Should never happen!
         }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7043a73..d758ecae 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -766,17 +766,18 @@
 
     @Override
     public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
-        File f = validateFilePath(name, true);
-        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
-        setFilePermissionsFromMode(f.getPath(), mode, 0);
-        return db;
+        return openOrCreateDatabase(name, mode, factory, null);
     }
 
     @Override
     public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
             DatabaseErrorHandler errorHandler) {
         File f = validateFilePath(name, true);
-        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
+        int flags = SQLiteDatabase.CREATE_IF_NECESSARY;
+        if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
+            flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
+        }
+        SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);
         setFilePermissionsFromMode(f.getPath(), mode, 0);
         return db;
     }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 03f22f8..1d994d8 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -105,7 +105,7 @@
     public List getServices(int maxNum, int flags) throws RemoteException;
     public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
             throws RemoteException;
-    public void moveTaskToFront(int task, int flags) throws RemoteException;
+    public void moveTaskToFront(int task, int flags, Bundle options) throws RemoteException;
     public void moveTaskToBack(int task) throws RemoteException;
     public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
     public void moveTaskBackwards(int task) throws RemoteException;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index de9470e..5340fbb 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -194,7 +194,7 @@
         ApplicationInfo ai = null;
         try {
             ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_SHARED_LIBRARY_FILES);
+                    PackageManager.GET_SHARED_LIBRARY_FILES, UserId.myUserId());
         } catch (RemoteException e) {
             throw new AssertionError(e);
         }
@@ -351,7 +351,7 @@
         IPackageManager pm = ActivityThread.getPackageManager();
         android.content.pm.PackageInfo pi;
         try {
-            pi = pm.getPackageInfo(mPackageName, 0);
+            pi = pm.getPackageInfo(mPackageName, 0, UserId.myUserId());
         } catch (RemoteException e) {
             throw new AssertionError(e);
         }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 741a6e9..2902504 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -99,6 +99,16 @@
     public static final int MODE_MULTI_PROCESS = 0x0004;
 
     /**
+     * Database open flag: when set, the database is opened with write-ahead
+     * logging enabled by default.
+     *
+     * @see #openOrCreateDatabase(String, int, CursorFactory)
+     * @see #openOrCreateDatabase(String, int, CursorFactory, DatabaseErrorHandler)
+     * @see SQLiteDatabase#enableWriteAheadLogging
+     */
+    public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008;
+
+    /**
      * Flag for {@link #bindService}: automatically create the service as long
      * as the binding exists.  Note that while this will create the service,
      * its {@link android.app.Service#onStartCommand}
@@ -691,6 +701,7 @@
      * @param mode Operating mode.  Use 0 or {@link #MODE_PRIVATE} for the
      *     default operation, {@link #MODE_WORLD_READABLE}
      *     and {@link #MODE_WORLD_WRITEABLE} to control permissions.
+     *     Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
      * @param factory An optional factory class that is called to instantiate a
      *     cursor when query is called.
      *
@@ -700,6 +711,7 @@
      * @see #MODE_PRIVATE
      * @see #MODE_WORLD_READABLE
      * @see #MODE_WORLD_WRITEABLE
+     * @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
      * @see #deleteDatabase
      */
     public abstract SQLiteDatabase openOrCreateDatabase(String name,
@@ -716,6 +728,7 @@
      * @param mode Operating mode.  Use 0 or {@link #MODE_PRIVATE} for the
      *     default operation, {@link #MODE_WORLD_READABLE}
      *     and {@link #MODE_WORLD_WRITEABLE} to control permissions.
+     *     Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
      * @param factory An optional factory class that is called to instantiate a
      *     cursor when query is called.
      * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
@@ -726,6 +739,7 @@
      * @see #MODE_PRIVATE
      * @see #MODE_WORLD_READABLE
      * @see #MODE_WORLD_WRITEABLE
+     * @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
      * @see #deleteDatabase
      */
     public abstract SQLiteDatabase openOrCreateDatabase(String name,
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 9bd1940..d89d2de 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -49,8 +49,8 @@
  *  {@hide}
  */
 interface IPackageManager {
-    PackageInfo getPackageInfo(String packageName, int flags);
-    int getPackageUid(String packageName);
+    PackageInfo getPackageInfo(String packageName, int flags, int userId);
+    int getPackageUid(String packageName, int userId);
     int[] getPackageGids(String packageName);
     
     String[] currentToCanonicalPackageNames(in String[] names);
@@ -64,15 +64,15 @@
     
     List<PermissionGroupInfo> getAllPermissionGroups(int flags);
     
-    ApplicationInfo getApplicationInfo(String packageName, int flags);
+    ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
 
-    ActivityInfo getActivityInfo(in ComponentName className, int flags);
+    ActivityInfo getActivityInfo(in ComponentName className, int flags, int userId);
 
-    ActivityInfo getReceiverInfo(in ComponentName className, int flags);
+    ActivityInfo getReceiverInfo(in ComponentName className, int flags, int userId);
 
-    ServiceInfo getServiceInfo(in ComponentName className, int flags);
+    ServiceInfo getServiceInfo(in ComponentName className, int flags, int userId);
 
-    ProviderInfo getProviderInfo(in ComponentName className, int flags);
+    ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);
 
     int checkPermission(String permName, String pkgName);
     
@@ -98,24 +98,24 @@
     
     int getUidForSharedUser(String sharedUserName);
     
-    ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags);
+    ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
 
     List<ResolveInfo> queryIntentActivities(in Intent intent, 
-            String resolvedType, int flags);
+            String resolvedType, int flags, int userId);
 
     List<ResolveInfo> queryIntentActivityOptions(
             in ComponentName caller, in Intent[] specifics,
             in String[] specificTypes, in Intent intent,
-            String resolvedType, int flags);
+            String resolvedType, int flags, int userId);
 
     List<ResolveInfo> queryIntentReceivers(in Intent intent,
-            String resolvedType, int flags);
+            String resolvedType, int flags, int userId);
 
     ResolveInfo resolveService(in Intent intent,
-            String resolvedType, int flags);
+            String resolvedType, int flags, int userId);
 
     List<ResolveInfo> queryIntentServices(in Intent intent,
-            String resolvedType, int flags);
+            String resolvedType, int flags, int userId);
 
     /**
      * This implements getInstalledPackages via a "last returned row"
@@ -131,7 +131,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
-    ParceledListSlice getInstalledApplications(int flags, in String lastRead);
+    ParceledListSlice getInstalledApplications(int flags, in String lastRead, int userId);
 
     /**
      * Retrieve all applications that are marked as persistent.
@@ -141,7 +141,7 @@
      */
     List<ApplicationInfo> getPersistentApplications(int flags);
 
-    ProviderInfo resolveContentProvider(String name, int flags);
+    ProviderInfo resolveContentProvider(String name, int flags, int userId);
 
     /**
      * Retrieve sync information for all content providers.
@@ -212,28 +212,28 @@
      * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
      */
     void setComponentEnabledSetting(in ComponentName componentName,
-            in int newState, in int flags);
+            in int newState, in int flags, int userId);
 
     /**
      * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}.
      */
-    int getComponentEnabledSetting(in ComponentName componentName);
+    int getComponentEnabledSetting(in ComponentName componentName, int userId);
     
     /**
      * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}.
      */
-    void setApplicationEnabledSetting(in String packageName, in int newState, int flags);
+    void setApplicationEnabledSetting(in String packageName, in int newState, int flags, int userId);
     
     /**
      * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}.
      */
-    int getApplicationEnabledSetting(in String packageName);
+    int getApplicationEnabledSetting(in String packageName, int userId);
     
     /**
      * Set whether the given package should be considered stopped, making
      * it not visible to implicit intents that filter out stopped packages.
      */
-    void setPackageStoppedState(String packageName, boolean stopped);
+    void setPackageStoppedState(String packageName, boolean stopped, int userId);
 
     /**
      * Free storage by deleting LRU sorted list of cache files across
@@ -296,7 +296,7 @@
      * files need to be deleted
      * @param observer a callback used to notify when the operation is completed.
      */
-    void clearApplicationUserData(in String packageName, IPackageDataObserver observer);
+    void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);
     
    /**
      * Get package statistics including the code, data and cache size for
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 207f077..07d231a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -240,7 +240,13 @@
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
             HashSet<String> grantedPermissions) {
 
-        final int userId = Binder.getOrigCallingUser();
+        return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
+                grantedPermissions, UserId.getCallingUserId());
+    }
+
+    static PackageInfo generatePackageInfo(PackageParser.Package p,
+            int gids[], int flags, long firstInstallTime, long lastUpdateTime,
+            HashSet<String> grantedPermissions, int userId) {
 
         PackageInfo pi = new PackageInfo();
         pi.packageName = p.packageName;
@@ -3350,7 +3356,7 @@
     }
 
     public static ApplicationInfo generateApplicationInfo(Package p, int flags) {
-        return generateApplicationInfo(p, flags, UserId.getUserId(Binder.getCallingUid()));
+        return generateApplicationInfo(p, flags, UserId.getCallingUserId());
     }
 
     public static ApplicationInfo generateApplicationInfo(Package p, int flags, int userId) {
@@ -3366,6 +3372,13 @@
             } else {
                 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
             }
+            if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+                p.applicationInfo.enabled = true;
+            } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                    || p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+                p.applicationInfo.enabled = false;
+            }
+            p.applicationInfo.enabledSetting = p.mSetEnabled;
             return p.applicationInfo;
         }
 
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index e2c222b..254f652 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -211,8 +211,8 @@
                 SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);
 
         setPageSize();
-        setSyncModeFromConfiguration();
-        setJournalModeFromConfiguration();
+        setForeignKeyModeFromConfiguration();
+        setWalModeFromConfiguration();
         setJournalSizeLimit();
         setAutoCheckpointInterval();
         setLocaleFromConfiguration();
@@ -268,31 +268,82 @@
         }
     }
 
-    private void setSyncModeFromConfiguration() {
-        if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
-            final String newValue = mConfiguration.syncMode;
-            String value = executeForString("PRAGMA synchronous", null, null);
-            if (!value.equalsIgnoreCase(newValue)) {
-                execute("PRAGMA synchronous=" + newValue, null, null);
+    private void setForeignKeyModeFromConfiguration() {
+        if (!mIsReadOnlyConnection) {
+            final long newValue = mConfiguration.foreignKeyConstraintsEnabled ? 1 : 0;
+            long value = executeForLong("PRAGMA foreign_keys", null, null);
+            if (value != newValue) {
+                execute("PRAGMA foreign_keys=" + newValue, null, null);
             }
         }
     }
 
-    private void setJournalModeFromConfiguration() {
+    private void setWalModeFromConfiguration() {
         if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
-            final String newValue = mConfiguration.journalMode;
-            String value = executeForString("PRAGMA journal_mode", null, null);
-            if (!value.equalsIgnoreCase(newValue)) {
-                value = executeForString("PRAGMA journal_mode=" + newValue, null, null);
-                if (!value.equalsIgnoreCase(newValue)) {
-                    Log.e(TAG, "setting journal_mode to " + newValue
-                            + " failed for db: " + mConfiguration.label
-                            + " (on pragma set journal_mode, sqlite returned:" + value);
-                }
+            if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
+                setJournalMode("WAL");
+                setSyncMode(SQLiteGlobal.getWALSyncMode());
+            } else {
+                setJournalMode(SQLiteGlobal.getDefaultJournalMode());
+                setSyncMode(SQLiteGlobal.getDefaultSyncMode());
             }
         }
     }
 
+    private void setSyncMode(String newValue) {
+        String value = executeForString("PRAGMA synchronous", null, null);
+        if (!canonicalizeSyncMode(value).equalsIgnoreCase(
+                canonicalizeSyncMode(newValue))) {
+            execute("PRAGMA synchronous=" + newValue, null, null);
+        }
+    }
+
+    private static String canonicalizeSyncMode(String value) {
+        if (value.equals("0")) {
+            return "OFF";
+        } else if (value.equals("1")) {
+            return "NORMAL";
+        } else if (value.equals("2")) {
+            return "FULL";
+        }
+        return value;
+    }
+
+    private void setJournalMode(String newValue) {
+        String value = executeForString("PRAGMA journal_mode", null, null);
+        if (!value.equalsIgnoreCase(newValue)) {
+            try {
+                String result = executeForString("PRAGMA journal_mode=" + newValue, null, null);
+                if (result.equalsIgnoreCase(newValue)) {
+                    return;
+                }
+                // PRAGMA journal_mode silently fails and returns the original journal
+                // mode in some cases if the journal mode could not be changed.
+            } catch (SQLiteDatabaseLockedException ex) {
+                // This error (SQLITE_BUSY) occurs if one connection has the database
+                // open in WAL mode and another tries to change it to non-WAL.
+            }
+            // Because we always disable WAL mode when a database is first opened
+            // (even if we intend to re-enable it), we can encounter problems if
+            // there is another open connection to the database somewhere.
+            // This can happen for a variety of reasons such as an application opening
+            // the same database in multiple processes at the same time or if there is a
+            // crashing content provider service that the ActivityManager has
+            // removed from its registry but whose process hasn't quite died yet
+            // by the time it is restarted in a new process.
+            //
+            // If we don't change the journal mode, nothing really bad happens.
+            // In the worst case, an application that enables WAL might not actually
+            // get it, although it can still use connection pooling.
+            Log.w(TAG, "Could not change the database journal mode of '"
+                    + mConfiguration.label + "' from '" + value + "' to '" + newValue
+                    + "' because the database is locked.  This usually means that "
+                    + "there are other open connections to the database which prevents "
+                    + "the database from enabling or disabling write-ahead logging mode.  "
+                    + "Proceeding without changing the journal mode.");
+        }
+    }
+
     private void setLocaleFromConfiguration() {
         if ((mConfiguration.openFlags & SQLiteDatabase.NO_LOCALIZED_COLLATORS) != 0) {
             return;
@@ -349,10 +400,10 @@
         }
 
         // Remember what changed.
-        boolean syncModeChanged = !configuration.syncMode.equalsIgnoreCase(
-                mConfiguration.syncMode);
-        boolean journalModeChanged = !configuration.journalMode.equalsIgnoreCase(
-                mConfiguration.journalMode);
+        boolean foreignKeyModeChanged = configuration.foreignKeyConstraintsEnabled
+                != mConfiguration.foreignKeyConstraintsEnabled;
+        boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
+                & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
         boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
 
         // Update configuration parameters.
@@ -361,14 +412,14 @@
         // Update prepared statement cache size.
         mPreparedStatementCache.resize(configuration.maxSqlCacheSize);
 
-        // Update sync mode.
-        if (syncModeChanged) {
-            setSyncModeFromConfiguration();
+        // Update foreign key mode.
+        if (foreignKeyModeChanged) {
+            setForeignKeyModeFromConfiguration();
         }
 
-        // Update journal mode.
-        if (journalModeChanged) {
-            setJournalModeFromConfiguration();
+        // Update WAL.
+        if (walModeChanged) {
+            setWalModeFromConfiguration();
         }
 
         // Update locale.
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index 00d3309..5c8e38bf 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -81,6 +81,7 @@
     private final Object mLock = new Object();
     private final AtomicBoolean mConnectionLeaked = new AtomicBoolean();
     private final SQLiteDatabaseConfiguration mConfiguration;
+    private int mMaxConnectionPoolSize;
     private boolean mIsOpen;
     private int mNextConnectionId;
 
@@ -146,6 +147,7 @@
 
     private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) {
         mConfiguration = new SQLiteDatabaseConfiguration(configuration);
+        setMaxConnectionPoolSizeLocked();
     }
 
     @Override
@@ -257,9 +259,9 @@
         synchronized (mLock) {
             throwIfClosedLocked();
 
-            boolean restrictToOneConnection = false;
-            if (mConfiguration.journalMode.equalsIgnoreCase("WAL")
-                    != configuration.journalMode.equalsIgnoreCase("WAL")) {
+            boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
+                    & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
+            if (walModeChanged) {
                 // WAL mode can only be changed if there are no acquired connections
                 // because we need to close all but the primary connection first.
                 if (!mAcquiredConnections.isEmpty()) {
@@ -273,15 +275,27 @@
                 // because none of them are in use.
                 closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
                 assert mAvailableNonPrimaryConnections.isEmpty();
+            }
 
-                restrictToOneConnection = true;
+            boolean foreignKeyModeChanged = configuration.foreignKeyConstraintsEnabled
+                    != mConfiguration.foreignKeyConstraintsEnabled;
+            if (foreignKeyModeChanged) {
+                // Foreign key constraints can only be changed if there are no transactions
+                // in progress.  To make this clear, we throw an exception if there are
+                // any acquired connections.
+                if (!mAcquiredConnections.isEmpty()) {
+                    throw new IllegalStateException("Foreign Key Constraints cannot "
+                            + "be enabled or disabled while there are transactions in "
+                            + "progress.  Finish all transactions and release all active "
+                            + "database connections first.");
+                }
             }
 
             if (mConfiguration.openFlags != configuration.openFlags) {
                 // If we are changing open flags and WAL mode at the same time, then
                 // we have no choice but to close the primary connection beforehand
                 // because there can only be one connection open when we change WAL mode.
-                if (restrictToOneConnection) {
+                if (walModeChanged) {
                     closeAvailableConnectionsAndLogExceptionsLocked();
                 }
 
@@ -297,9 +311,11 @@
 
                 mAvailablePrimaryConnection = newPrimaryConnection;
                 mConfiguration.updateParametersFrom(configuration);
+                setMaxConnectionPoolSizeLocked();
             } else {
                 // Reconfigure the database connections in place.
                 mConfiguration.updateParametersFrom(configuration);
+                setMaxConnectionPoolSizeLocked();
 
                 closeExcessConnectionsAndLogExceptionsLocked();
                 reconfigureAllConnectionsLocked();
@@ -361,8 +377,7 @@
                     mAvailablePrimaryConnection = connection;
                 }
                 wakeConnectionWaitersLocked();
-            } else if (mAvailableNonPrimaryConnections.size() >=
-                    mConfiguration.maxConnectionPoolSize - 1) {
+            } else if (mAvailableNonPrimaryConnections.size() >= mMaxConnectionPoolSize - 1) {
                 closeConnectionAndLogExceptionsLocked(connection);
             } else {
                 if (recycleConnectionLocked(connection, status)) {
@@ -500,7 +515,7 @@
     // Can't throw.
     private void closeExcessConnectionsAndLogExceptionsLocked() {
         int availableCount = mAvailableNonPrimaryConnections.size();
-        while (availableCount-- > mConfiguration.maxConnectionPoolSize - 1) {
+        while (availableCount-- > mMaxConnectionPoolSize - 1) {
             SQLiteConnection connection =
                     mAvailableNonPrimaryConnections.remove(availableCount);
             closeConnectionAndLogExceptionsLocked(connection);
@@ -875,7 +890,7 @@
         if (mAvailablePrimaryConnection != null) {
             openConnections += 1;
         }
-        if (openConnections >= mConfiguration.maxConnectionPoolSize) {
+        if (openConnections >= mMaxConnectionPoolSize) {
             return null;
         }
         connection = openConnectionLocked(mConfiguration,
@@ -927,6 +942,18 @@
         return (connectionFlags & CONNECTION_FLAG_INTERACTIVE) != 0 ? 1 : 0;
     }
 
+    private void setMaxConnectionPoolSizeLocked() {
+        if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
+            mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
+        } else {
+            // TODO: We don't actually need to restrict the connection pool size to 1
+            // for non-WAL databases.  There might be reasons to use connection pooling
+            // with other journal modes.  For now, enabling connection pooling and
+            // using WAL are the same thing in the API.
+            mMaxConnectionPoolSize = 1;
+        }
+    }
+
     private void throwIfClosedLocked() {
         if (!mIsOpen) {
             throw new IllegalStateException("Cannot perform this operation "
@@ -973,7 +1000,7 @@
         synchronized (mLock) {
             printer.println("Connection pool for " + mConfiguration.path + ":");
             printer.println("  Open: " + mIsOpen);
-            printer.println("  Max connections: " + mConfiguration.maxConnectionPoolSize);
+            printer.println("  Max connections: " + mMaxConnectionPoolSize);
 
             printer.println("  Available primary connection:");
             if (mAvailablePrimaryConnection != null) {
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 24a7800..7bd0c8d 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -127,10 +127,6 @@
     // INVARIANT: Guarded by mLock.
     private boolean mHasAttachedDbsLocked;
 
-    // True if the database is in WAL mode.
-    // INVARIANT: Guarded by mLock.
-    private boolean mIsWALEnabledLocked;
-
     /**
      * When a constraint violation occurs, an immediate ROLLBACK occurs,
      * thus ending the current transaction, and the command aborts with a
@@ -236,6 +232,18 @@
     public static final int CREATE_IF_NECESSARY = 0x10000000;     // update native code if changing
 
     /**
+     * Open flag: Flag for {@link #openDatabase} to open the database file with
+     * write-ahead logging enabled by default.  Using this flag is more efficient
+     * than calling {@link #enableWriteAheadLogging}.
+     *
+     * Write-ahead logging cannot be used with read-only databases so the value of
+     * this flag is ignored if the database is opened read-only.
+     *
+     * @see #enableWriteAheadLogging
+     */
+    public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000;
+
+    /**
      * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}.
      *
      * Each prepared-statement is between 1K - 6K, depending on the complexity of the
@@ -658,7 +666,7 @@
      * @throws SQLiteException if the database cannot be opened
      */
     public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) {
-        return openDatabase(path, factory, flags, new DefaultDatabaseErrorHandler());
+        return openDatabase(path, factory, flags, null);
     }
 
     /**
@@ -698,7 +706,7 @@
      * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
      */
     public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) {
-        return openDatabase(path, factory, CREATE_IF_NECESSARY);
+        return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
     }
 
     /**
@@ -1785,56 +1793,131 @@
     }
 
     /**
-     * This method enables parallel execution of queries from multiple threads on the same database.
-     * It does this by opening multiple handles to the database and using a different
-     * database handle for each query.
+     * Sets whether foreign key constraints are enabled for the database.
      * <p>
-     * If a transaction is in progress on one connection handle and say, a table is updated in the
-     * transaction, then query on the same table on another connection handle will block for the
-     * transaction to complete. But this method enables such queries to execute by having them
-     * return old version of the data from the table. Most often it is the data that existed in the
-     * table prior to the above transaction updates on that table.
-     * <p>
-     * Maximum number of simultaneous handles used to execute queries in parallel is
-     * dependent upon the device memory and possibly other properties.
-     * <p>
-     * After calling this method, execution of queries in parallel is enabled as long as this
-     * database handle is open. To disable execution of queries in parallel, database should
-     * be closed and reopened.
-     * <p>
-     * If a query is part of a transaction, then it is executed on the same database handle the
-     * transaction was begun.
-     * <p>
-     * If the database has any attached databases, then execution of queries in paralel is NOT
-     * possible. In such cases, a message is printed to logcat and false is returned.
-     * <p>
-     * This feature is not available for :memory: databases. In such cases,
-     * a message is printed to logcat and false is returned.
-     * <p>
-     * A typical way to use this method is the following:
-     * <pre>
-     *     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
-     *             CREATE_IF_NECESSARY, myDatabaseErrorHandler);
-     *     db.enableWriteAheadLogging();
-     * </pre>
-     * <p>
-     * Writers should use {@link #beginTransactionNonExclusive()} or
-     * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
-     * to start a trsnsaction.
-     * Non-exclusive mode allows database file to be in readable by threads executing queries.
+     * By default, foreign key constraints are not enforced by the database.
+     * This method allows an application to enable foreign key constraints.
+     * It must be called each time the database is opened to ensure that foreign
+     * key constraints are enabled for the session.
+     * </p><p>
+     * A good time to call this method is right after calling {@link #openOrCreateDatabase}
+     * or in the {@link SQLiteOpenHelper#onConfigure} callback.
+     * </p><p>
+     * When foreign key constraints are disabled, the database does not check whether
+     * changes to the database will violate foreign key constraints.  Likewise, when
+     * foreign key constraints are disabled, the database will not execute cascade
+     * delete or update triggers.  As a result, it is possible for the database
+     * state to become inconsistent.  To perform a database integrity check,
+     * call {@link #isDatabaseIntegrityOk}.
+     * </p><p>
+     * This method must not be called while a transaction is in progress.
+     * </p><p>
+     * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
+     * for more details about foreign key constraint support.
      * </p>
      *
-     * @return true if write-ahead-logging is set. false otherwise
+     * @param enable True to enable foreign key constraints, false to disable them.
+     *
+     * @throws IllegalStateException if the are transactions is in progress
+     * when this method is called.
+     */
+    public void setForeignKeyConstraintsEnabled(boolean enable) {
+        synchronized (mLock) {
+            throwIfNotOpenLocked();
+
+            if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) {
+                return;
+            }
+
+            mConfigurationLocked.foreignKeyConstraintsEnabled = enable;
+            try {
+                mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+            } catch (RuntimeException ex) {
+                mConfigurationLocked.foreignKeyConstraintsEnabled = !enable;
+                throw ex;
+            }
+        }
+    }
+
+    /**
+     * This method enables parallel execution of queries from multiple threads on the
+     * same database.  It does this by opening multiple connections to the database
+     * and using a different database connection for each query.  The database
+     * journal mode is also changed to enable writes to proceed concurrently with reads.
+     * <p>
+     * When write-ahead logging is not enabled (the default), it is not possible for
+     * reads and writes to occur on the database at the same time.  Before modifying the
+     * database, the writer implicitly acquires an exclusive lock on the database which
+     * prevents readers from accessing the database until the write is completed.
+     * </p><p>
+     * In contrast, when write-ahead logging is enabled (by calling this method), write
+     * operations occur in a separate log file which allows reads to proceed concurrently.
+     * While a write is in progress, readers on other threads will perceive the state
+     * of the database as it was before the write began.  When the write completes, readers
+     * on other threads will then perceive the new state of the database.
+     * </p><p>
+     * It is a good idea to enable write-ahead logging whenever a database will be
+     * concurrently accessed and modified by multiple threads at the same time.
+     * However, write-ahead logging uses significantly more memory than ordinary
+     * journaling because there are multiple connections to the same database.
+     * So if a database will only be used by a single thread, or if optimizing
+     * concurrency is not very important, then write-ahead logging should be disabled.
+     * </p><p>
+     * After calling this method, execution of queries in parallel is enabled as long as
+     * the database remains open.  To disable execution of queries in parallel, either
+     * call {@link #disableWriteAheadLogging} or close the database and reopen it.
+     * </p><p>
+     * The maximum number of connections used to execute queries in parallel is
+     * dependent upon the device memory and possibly other properties.
+     * </p><p>
+     * If a query is part of a transaction, then it is executed on the same database handle the
+     * transaction was begun.
+     * </p><p>
+     * Writers should use {@link #beginTransactionNonExclusive()} or
+     * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
+     * to start a transaction.  Non-exclusive mode allows database file to be in readable
+     * by other threads executing queries.
+     * </p><p>
+     * If the database has any attached databases, then execution of queries in parallel is NOT
+     * possible.  Likewise, write-ahead logging is not supported for read-only databases
+     * or memory databases.  In such cases, {@link #enableWriteAheadLogging} returns false.
+     * </p><p>
+     * The best way to enable write-ahead logging is to pass the
+     * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}.  This is
+     * more efficient than calling {@link #enableWriteAheadLogging}.
+     * <code><pre>
+     *     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
+     *             SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
+     *             myDatabaseErrorHandler);
+     *     db.enableWriteAheadLogging();
+     * </pre></code>
+     * </p><p>
+     * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging}
+     * after opening the database.
+     * <code><pre>
+     *     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
+     *             SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
+     *     db.enableWriteAheadLogging();
+     * </pre></code>
+     * </p><p>
+     * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
+     * more details about how write-ahead logging works.
+     * </p>
+     *
+     * @return True if write-ahead logging is enabled.
      *
      * @throws IllegalStateException if there are transactions in progress at the
      * time this method is called.  WAL mode can only be changed when there are no
      * transactions in progress.
+     *
+     * @see #ENABLE_WRITE_AHEAD_LOGGING
+     * @see #disableWriteAheadLogging
      */
     public boolean enableWriteAheadLogging() {
         synchronized (mLock) {
             throwIfNotOpenLocked();
 
-            if (mIsWALEnabledLocked) {
+            if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) {
                 return true;
             }
 
@@ -1859,22 +1942,13 @@
                 return false;
             }
 
-            final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
-            final String oldSyncMode = mConfigurationLocked.syncMode;
-            final String oldJournalMode = mConfigurationLocked.journalMode;
-            mConfigurationLocked.maxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
-            mConfigurationLocked.syncMode = SQLiteGlobal.getWALSyncMode();
-            mConfigurationLocked.journalMode = "WAL";
+            mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
             try {
                 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
             } catch (RuntimeException ex) {
-                mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
-                mConfigurationLocked.syncMode = oldSyncMode;
-                mConfigurationLocked.journalMode = oldJournalMode;
+                mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
                 throw ex;
             }
-
-            mIsWALEnabledLocked = true;
         }
         return true;
     }
@@ -1885,31 +1959,40 @@
      * @throws IllegalStateException if there are transactions in progress at the
      * time this method is called.  WAL mode can only be changed when there are no
      * transactions in progress.
+     *
+     * @see #enableWriteAheadLogging
      */
     public void disableWriteAheadLogging() {
         synchronized (mLock) {
             throwIfNotOpenLocked();
 
-            if (!mIsWALEnabledLocked) {
+            if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
                 return;
             }
 
-            final int oldMaxConnectionPoolSize = mConfigurationLocked.maxConnectionPoolSize;
-            final String oldSyncMode = mConfigurationLocked.syncMode;
-            final String oldJournalMode = mConfigurationLocked.journalMode;
-            mConfigurationLocked.maxConnectionPoolSize = 1;
-            mConfigurationLocked.syncMode = SQLiteGlobal.getDefaultSyncMode();
-            mConfigurationLocked.journalMode = SQLiteGlobal.getDefaultJournalMode();
+            mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
             try {
                 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
             } catch (RuntimeException ex) {
-                mConfigurationLocked.maxConnectionPoolSize = oldMaxConnectionPoolSize;
-                mConfigurationLocked.syncMode = oldSyncMode;
-                mConfigurationLocked.journalMode = oldJournalMode;
+                mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
                 throw ex;
             }
+        }
+    }
 
-            mIsWALEnabledLocked = false;
+    /**
+     * Returns true if write-ahead logging has been enabled for this database.
+     *
+     * @return True if write-ahead logging has been enabled for this database.
+     *
+     * @see #enableWriteAheadLogging
+     * @see #ENABLE_WRITE_AHEAD_LOGGING
+     */
+    public boolean isWriteAheadLoggingEnabled() {
+        synchronized (mLock) {
+            throwIfNotOpenLocked();
+
+            return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
         }
     }
 
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index efbcaca..549ab90 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -62,14 +62,6 @@
     public int openFlags;
 
     /**
-     * The maximum number of connections to retain in the connection pool.
-     * Must be at least 1.
-     *
-     * Default is 1.
-     */
-    public int maxConnectionPoolSize;
-
-    /**
      * The maximum size of the prepared statement cache for each database connection.
      * Must be non-negative.
      *
@@ -85,18 +77,11 @@
     public Locale locale;
 
     /**
-     * The database synchronization mode.
+     * True if foreign key constraints are enabled.
      *
-     * Default is {@link SQLiteGlobal#getDefaultSyncMode()}.
+     * Default is false.
      */
-    public String syncMode;
-
-    /**
-     * The database journal mode.
-     *
-     * Default is {@link SQLiteGlobal#getDefaultJournalMode()}.
-     */
-    public String journalMode;
+    public boolean foreignKeyConstraintsEnabled;
 
     /**
      * The custom functions to register.
@@ -121,11 +106,8 @@
         this.openFlags = openFlags;
 
         // Set default values for optional parameters.
-        maxConnectionPoolSize = 1;
         maxSqlCacheSize = 25;
         locale = Locale.getDefault();
-        syncMode = SQLiteGlobal.getDefaultSyncMode();
-        journalMode = SQLiteGlobal.getDefaultJournalMode();
     }
 
     /**
@@ -159,11 +141,9 @@
         }
 
         openFlags = other.openFlags;
-        maxConnectionPoolSize = other.maxConnectionPoolSize;
         maxSqlCacheSize = other.maxSqlCacheSize;
         locale = other.locale;
-        syncMode = other.syncMode;
-        journalMode = other.journalMode;
+        foreignKeyConstraintsEnabled = other.foreignKeyConstraintsEnabled;
         customFunctions.clear();
         customFunctions.addAll(other.customFunctions);
     }
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index ffa4663..431eca2 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -58,6 +58,7 @@
 
     private SQLiteDatabase mDatabase;
     private boolean mIsInitializing;
+    private boolean mEnableWriteAheadLogging;
     private final DatabaseErrorHandler mErrorHandler;
 
     /**
@@ -74,7 +75,7 @@
      *     newer, {@link #onDowngrade} will be used to downgrade the database
      */
     public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
-        this(context, name, factory, version, new DefaultDatabaseErrorHandler());
+        this(context, name, factory, version, null);
     }
 
     /**
@@ -92,14 +93,11 @@
      *     {@link #onUpgrade} will be used to upgrade the database; if the database is
      *     newer, {@link #onDowngrade} will be used to downgrade the database
      * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
-     * corruption.
+     * corruption, or null to use the default error handler.
      */
     public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
             DatabaseErrorHandler errorHandler) {
         if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
-        if (errorHandler == null) {
-            throw new IllegalArgumentException("DatabaseErrorHandler param value can't be null.");
-        }
 
         mContext = context;
         mName = name;
@@ -117,6 +115,32 @@
     }
 
     /**
+     * Enables or disables the use of write-ahead logging for the database.
+     *
+     * Write-ahead logging cannot be used with read-only databases so the value of
+     * this flag is ignored if the database is opened read-only.
+     *
+     * @param enabled True if write-ahead logging should be enabled, false if it
+     * should be disabled.
+     *
+     * @see SQLiteDatabase#enableWriteAheadLogging()
+     */
+    public void setWriteAheadLoggingEnabled(boolean enabled) {
+        synchronized (this) {
+            if (mEnableWriteAheadLogging != enabled) {
+                if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
+                    if (enabled) {
+                        mDatabase.enableWriteAheadLogging();
+                    } else {
+                        mDatabase.disableWriteAheadLogging();
+                    }
+                }
+                mEnableWriteAheadLogging = enabled;
+            }
+        }
+    }
+
+    /**
      * Create and/or open a database that will be used for reading and writing.
      * The first time this is called, the database will be opened and
      * {@link #onCreate}, {@link #onUpgrade} and/or {@link #onOpen} will be
@@ -197,7 +221,9 @@
                         db = SQLiteDatabase.openDatabase(path, mFactory,
                                 SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                     } else {
-                        db = mContext.openOrCreateDatabase(mName, 0, mFactory, mErrorHandler);
+                        db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
+                                Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
+                                mFactory, mErrorHandler);
                     }
                 } catch (SQLiteException ex) {
                     if (writable) {
@@ -211,6 +237,8 @@
                 }
             }
 
+            onConfigure(db);
+
             final int version = db.getVersion();
             if (version != mNewVersion) {
                 if (db.isReadOnly()) {
@@ -235,6 +263,7 @@
                     db.endTransaction();
                 }
             }
+
             onOpen(db);
 
             if (db.isReadOnly()) {
@@ -264,6 +293,25 @@
     }
 
     /**
+     * Called when the database connection is being configured, to enable features
+     * such as write-ahead logging or foreign key support.
+     * <p>
+     * This method is called before {@link #onCreate}, {@link #onUpgrade},
+     * {@link #onDowngrade}, or {@link #onOpen} are called.  It should not modify
+     * the database except to configure the database connection as required.
+     * </p><p>
+     * This method should only call methods that configure the parameters of the
+     * database connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
+     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled},
+     * {@link SQLiteDatabase#setLocale}, {@link SQLiteDatabase#setMaximumSize},
+     * or executing PRAGMA statements.
+     * </p>
+     *
+     * @param db The database.
+     */
+    public void onConfigure(SQLiteDatabase db) {}
+
+    /**
      * Called when the database is created for the first time. This is where the
      * creation of tables and the initial population of the tables should happen.
      *
@@ -276,11 +324,16 @@
      * should use this method to drop tables, add tables, or do anything else it
      * needs to upgrade to the new schema version.
      *
-     * <p>The SQLite ALTER TABLE documentation can be found
+     * <p>
+     * The SQLite ALTER TABLE documentation can be found
      * <a href="http://sqlite.org/lang_altertable.html">here</a>. If you add new columns
      * you can use ALTER TABLE to insert them into a live table. If you rename or remove columns
      * you can use ALTER TABLE to rename the old table, then create the new table and then
      * populate the new table with the contents of the old table.
+     * </p><p>
+     * This method executes within a transaction.  If an exception is thrown, all changes
+     * will automatically be rolled back.
+     * </p>
      *
      * @param db The database.
      * @param oldVersion The old database version.
@@ -290,11 +343,16 @@
 
     /**
      * Called when the database needs to be downgraded. This is strictly similar to
-     * onUpgrade() method, but is called whenever current version is newer than requested one.
+     * {@link #onUpgrade} method, but is called whenever current version is newer than requested one.
      * However, this method is not abstract, so it is not mandatory for a customer to
      * implement it. If not overridden, default implementation will reject downgrade and
      * throws SQLiteException
      *
+     * <p>
+     * This method executes within a transaction.  If an exception is thrown, all changes
+     * will automatically be rolled back.
+     * </p>
+     *
      * @param db The database.
      * @param oldVersion The old database version.
      * @param newVersion The new database version.
@@ -308,6 +366,12 @@
      * Called when the database has been opened.  The implementation
      * should check {@link SQLiteDatabase#isReadOnly} before updating the
      * database.
+     * <p>
+     * This method is called after the database connection has been configured
+     * and after the database schema has been created, upgraded or downgraded as necessary.
+     * If the database connection must be configured in some way before the schema
+     * is created, upgraded, or downgraded, do it in {@link #onConfigure} instead.
+     * </p>
      *
      * @param db The database.
      */
diff --git a/core/java/android/os/UserId.java b/core/java/android/os/UserId.java
index cf6ce2c..8bf6c6e 100644
--- a/core/java/android/os/UserId.java
+++ b/core/java/android/os/UserId.java
@@ -105,4 +105,12 @@
     public static final int getAppId(int uid) {
         return uid % PER_USER_RANGE;
     }
+
+    /**
+     * Returns the user id of the current process
+     * @return user id of the current process
+     */
+    public static final int myUserId() {
+        return getUserId(Process.myUid());
+    }
 }
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index fecc8f9..850349b 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -46,6 +46,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.content.res.Resources;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -554,12 +555,15 @@
     private synchronized void updateSdpRecords() {
         ArrayList<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
 
-        // Add the default records
-        uuids.add(BluetoothUuid.HSP_AG);
-        uuids.add(BluetoothUuid.ObexObjectPush);
+        Resources R = mContext.getResources();
 
-        if (mContext.getResources().
-                getBoolean(com.android.internal.R.bool.config_voice_capable)) {
+        // Add the default records
+        if (R.getBoolean(com.android.internal.R.bool.config_bluetooth_default_profiles)) {
+            uuids.add(BluetoothUuid.HSP_AG);
+            uuids.add(BluetoothUuid.ObexObjectPush);
+        }
+
+        if (R.getBoolean(com.android.internal.R.bool.config_voice_capable)) {
             uuids.add(BluetoothUuid.Handsfree_AG);
             uuids.add(BluetoothUuid.PBAP_PSE);
         }
@@ -567,14 +571,16 @@
         // Add SDP records for profiles maintained by Android userspace
         addReservedSdpRecords(uuids);
 
-        // Enable profiles maintained by Bluez userspace.
-        setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE,
-                BluetoothPanProfileHandler.NAP_BRIDGE);
+        if (R.getBoolean(com.android.internal.R.bool.config_bluetooth_default_profiles)) {
+            // Enable profiles maintained by Bluez userspace.
+            setBluetoothTetheringNative(true, BluetoothPanProfileHandler.NAP_ROLE,
+                   BluetoothPanProfileHandler.NAP_BRIDGE);
 
-        // Add SDP records for profiles maintained by Bluez userspace
-        uuids.add(BluetoothUuid.AudioSource);
-        uuids.add(BluetoothUuid.AvrcpTarget);
-        uuids.add(BluetoothUuid.NAP);
+            // Add SDP records for profiles maintained by Bluez userspace
+            uuids.add(BluetoothUuid.AudioSource);
+            uuids.add(BluetoothUuid.AvrcpTarget);
+            uuids.add(BluetoothUuid.NAP);
+        }
 
         // Cannot cast uuids.toArray directly since ParcelUuid is parcelable
         mAdapterUuids = new ParcelUuid[uuids.size()];
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 1dabad2..a50f09f 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -16,8 +16,6 @@
 
 package android.view;
 
-import android.os.Handler;
-
 /**
  * A display lists records a series of graphics related operation and can replay
  * them later. Display lists are usually built by recording operations on a
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index b98257c..1f140e95 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -464,8 +464,8 @@
         static final Object[] sEglLock = new Object[0];
         int mWidth = -1, mHeight = -1;
 
-        static final ThreadLocal<Gl20Renderer.Gl20RendererEglContext> sEglContextStorage
-                = new ThreadLocal<Gl20Renderer.Gl20RendererEglContext>();
+        static final ThreadLocal<ManagedEGLContext> sEglContextStorage
+                = new ThreadLocal<ManagedEGLContext>();
 
         EGLContext mEglContext;
         Thread mEglThread;
@@ -622,7 +622,7 @@
             }
         }
 
-        abstract GLES20Canvas createCanvas();
+        abstract HardwareCanvas createCanvas();
 
         abstract int[] getConfig(boolean dirtyRegions);
 
@@ -662,16 +662,18 @@
                 }
             }
 
-            Gl20Renderer.Gl20RendererEglContext managedContext = sEglContextStorage.get();
+            ManagedEGLContext managedContext = sEglContextStorage.get();
             mEglContext = managedContext != null ? managedContext.getContext() : null;
             mEglThread = Thread.currentThread();
 
             if (mEglContext == null) {
                 mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
-                sEglContextStorage.set(new Gl20Renderer.Gl20RendererEglContext(mEglContext));
+                sEglContextStorage.set(createManagedContext(mEglContext));
             }
         }
 
+        abstract ManagedEGLContext createManagedContext(EGLContext eglContext);
+
         private EGLConfig chooseEglConfig() {
             EGLConfig[] configs = new EGLConfig[1];
             int[] configsCount = new int[1];
@@ -1103,7 +1105,8 @@
                 // Make sure we do this on the correct thread.
                 if (mHandler.getLooper() != Looper.myLooper()) {
                     mHandler.post(new Runnable() {
-                        @Override public void run() {
+                        @Override
+                        public void run() {
                             onTerminate(eglContext);
                         }
                     });
@@ -1142,11 +1145,16 @@
         }
 
         @Override
-        GLES20Canvas createCanvas() {
+        HardwareCanvas createCanvas() {
             return mGlCanvas = new GLES20Canvas(mTranslucent);
         }
 
         @Override
+        ManagedEGLContext createManagedContext(EGLContext eglContext) {
+            return new Gl20Renderer.Gl20RendererEglContext(mEglContext);
+        }
+
+        @Override
         int[] getConfig(boolean dirtyRegions) {
             return new int[] {
                     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
@@ -1249,7 +1257,8 @@
                 if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
 
                 if (needsContext) {
-                    Gl20RendererEglContext managedContext = sEglContextStorage.get();
+                    Gl20RendererEglContext managedContext =
+                            (Gl20RendererEglContext) sEglContextStorage.get();
                     if (managedContext == null) return;
                     usePbufferSurface(managedContext.getContext());
                 }
@@ -1282,7 +1291,8 @@
         static void trimMemory(int level) {
             if (sEgl == null || sEglConfig == null) return;
 
-            Gl20RendererEglContext managedContext = sEglContextStorage.get();
+            Gl20RendererEglContext managedContext =
+                    (Gl20RendererEglContext) sEglContextStorage.get();
             // We do not have OpenGL objects
             if (managedContext == null) {
                 return;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c54d09e..14cd48f 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -89,6 +89,8 @@
     void prepareAppTransition(int transit, boolean alwaysKeepCurrent);
     int getPendingAppTransition();
     void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim);
+    void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
+            IRemoteCallback startedCallback);
     void executeAppTransition();
     void setAppStartingWindow(IBinder token, String pkg, int theme,
             in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index edaa262..eb80290d 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -20,6 +20,7 @@
 import android.graphics.*;
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.SystemProperties;
 import android.util.Log;
 
 /**
@@ -35,6 +36,15 @@
     public static final int ROTATION_180     = 2;
     public static final int ROTATION_270     = 3;
 
+    private static final boolean headless = "1".equals(
+        SystemProperties.get("ro.config.headless", "0"));
+
+    private static void checkHeadless() {
+        if(headless) {
+            throw new UnsupportedOperationException("Device is headless");
+        }
+    }
+
     /**
      * Create Surface from a {@link SurfaceTexture}.
      *
@@ -46,6 +56,8 @@
      * Surface.
      */
     public Surface(SurfaceTexture surfaceTexture) {
+        checkHeadless();
+
         if (DEBUG_RELEASE) {
             mCreationStack = new Exception();
         }
@@ -244,6 +256,8 @@
     public Surface(SurfaceSession s,
             int pid, int display, int w, int h, int format, int flags)
         throws OutOfResourcesException {
+        checkHeadless();
+
         if (DEBUG_RELEASE) {
             mCreationStack = new Exception();
         }
@@ -255,6 +269,8 @@
     public Surface(SurfaceSession s,
             int pid, String name, int display, int w, int h, int format, int flags)
         throws OutOfResourcesException {
+        checkHeadless();
+
         if (DEBUG_RELEASE) {
             mCreationStack = new Exception();
         }
@@ -269,6 +285,8 @@
      * @hide
      */
     public Surface() {
+        checkHeadless();
+
         if (DEBUG_RELEASE) {
             mCreationStack = new Exception();
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ffffc73..770d899 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1707,25 +1707,25 @@
      * Horizontal layout direction of this view is from Left to Right.
      * Use with {@link #setLayoutDirection}.
      */
-    public static final int LAYOUT_DIRECTION_LTR = 0x00000001;
+    public static final int LAYOUT_DIRECTION_LTR = 0;
 
     /**
      * Horizontal layout direction of this view is from Right to Left.
      * Use with {@link #setLayoutDirection}.
      */
-    public static final int LAYOUT_DIRECTION_RTL = 0x00000002;
+    public static final int LAYOUT_DIRECTION_RTL = 1;
 
     /**
      * Horizontal layout direction of this view is inherited from its parent.
      * Use with {@link #setLayoutDirection}.
      */
-    public static final int LAYOUT_DIRECTION_INHERIT = 0x00000004;
+    public static final int LAYOUT_DIRECTION_INHERIT = 2;
 
     /**
      * Horizontal layout direction of this view is from deduced from the default language
      * script for the locale. Use with {@link #setLayoutDirection}.
      */
-    public static final int LAYOUT_DIRECTION_LOCALE = 0x00000008;
+    public static final int LAYOUT_DIRECTION_LOCALE = 3;
 
     /**
      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
@@ -1737,34 +1737,38 @@
      * Mask for use with private flags indicating bits used for horizontal layout direction.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_MASK = 0x0000000F << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int LAYOUT_DIRECTION_MASK = 0x00000003 << 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 = 0x00000010 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int LAYOUT_DIRECTION_RESOLVED_RTL = 4 << LAYOUT_DIRECTION_MASK_SHIFT;
 
     /**
      * Indicates whether the view horizontal layout direction has been resolved.
      * @hide
      */
-    static final int LAYOUT_DIRECTION_RESOLVED = 0x00000020 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int LAYOUT_DIRECTION_RESOLVED = 8 << 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 = 0x00000030 << LAYOUT_DIRECTION_MASK_SHIFT;
+    static final int LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C << LAYOUT_DIRECTION_MASK_SHIFT;
 
     /*
      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
      * flag value.
      * @hide
      */
-    private static final int[] LAYOUT_DIRECTION_FLAGS = {LAYOUT_DIRECTION_LTR,
-            LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LOCALE};
+    private static final int[] LAYOUT_DIRECTION_FLAGS = {
+            LAYOUT_DIRECTION_LTR,
+            LAYOUT_DIRECTION_RTL,
+            LAYOUT_DIRECTION_INHERIT,
+            LAYOUT_DIRECTION_LOCALE
+    };
 
     /**
      * Default horizontal layout direction.
@@ -1783,6 +1787,97 @@
     static final int HAS_TRANSIENT_STATE = 0x00000100;
 
 
+    /**
+     * Text direction is inherited thru {@link ViewGroup}
+     */
+    public static final int TEXT_DIRECTION_INHERIT = 0;
+
+    /**
+     * Text direction is using "first strong algorithm". The first strong directional character
+     * determines the paragraph direction. If there is no strong directional character, the
+     * paragraph direction is the view's resolved layout direction.
+     */
+    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
+
+    /**
+     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
+     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
+     * If there are neither, the paragraph direction is the view's resolved layout direction.
+     */
+    public static final int TEXT_DIRECTION_ANY_RTL = 2;
+
+    /**
+     * Text direction is forced to LTR.
+     */
+    public static final int TEXT_DIRECTION_LTR = 3;
+
+    /**
+     * Text direction is forced to RTL.
+     */
+    public static final int TEXT_DIRECTION_RTL = 4;
+
+    /**
+     * Text direction is coming from the system Locale.
+     */
+    public static final int TEXT_DIRECTION_LOCALE = 5;
+
+    /**
+     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
+     * @hide
+     */
+    static final int TEXT_DIRECTION_MASK_SHIFT = 6;
+
+    /**
+     * Default text direction is inherited
+     */
+    protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
+
+    /**
+     * Mask for use with private flags indicating bits used for text direction.
+     * @hide
+     */
+    static final int TEXT_DIRECTION_MASK = 0x00000007 << 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
+    };
+
+    /**
+     * Indicates whether the view text direction has been resolved.
+     * @hide
+     */
+    static final int TEXT_DIRECTION_RESOLVED = 0x00000008 << 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;
+
+    /**
+     * 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;
+
+    /**
+     * 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;
+
+
     /* End of masks for mPrivateFlags2 */
 
     static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
@@ -2657,82 +2752,6 @@
     AccessibilityDelegate mAccessibilityDelegate;
 
     /**
-     * Text direction is inherited thru {@link ViewGroup}
-     */
-    public static final int TEXT_DIRECTION_INHERIT = 0;
-
-    /**
-     * Text direction is using "first strong algorithm". The first strong directional character
-     * determines the paragraph direction. If there is no strong directional character, the
-     * paragraph direction is the view's resolved layout direction.
-     *
-     */
-    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
-
-    /**
-     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
-     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
-     * If there are neither, the paragraph direction is the view's resolved layout direction.
-     *
-     */
-    public static final int TEXT_DIRECTION_ANY_RTL = 2;
-
-    /**
-     * Text direction is forced to LTR.
-     *
-     */
-    public static final int TEXT_DIRECTION_LTR = 3;
-
-    /**
-     * Text direction is forced to RTL.
-     *
-     */
-    public static final int TEXT_DIRECTION_RTL = 4;
-
-    /**
-     * Text direction is coming from the system Locale.
-     *
-     */
-    public static final int TEXT_DIRECTION_LOCALE = 5;
-
-    /**
-     * Default text direction is inherited
-     *
-     */
-    protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
-
-    /**
-     * The text direction that has been defined by {@link #setTextDirection(int)}.
-     *
-     */
-    @ViewDebug.ExportedProperty(category = "text", mapping = {
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
-    })
-    private int mTextDirection = DEFAULT_TEXT_DIRECTION;
-
-    /**
-     * The resolved text direction.  This needs resolution if the value is
-     * TEXT_DIRECTION_INHERIT.  The resolution matches mTextDirection if it is
-     * not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent
-     * chain of the view.
-     *
-     */
-    @ViewDebug.ExportedProperty(category = "text", mapping = {
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
-            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
-    })
-    private int mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
-
-    /**
      * Consistency verifier for debugging purposes.
      * @hide
      */
@@ -2750,7 +2769,9 @@
         mContext = context;
         mResources = context != null ? context.getResources() : null;
         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
-        mPrivateFlags2 |= (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT);
+        // Set layout and text direction defaults
+        mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
+                (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
         mUserPaddingStart = -1;
@@ -3110,7 +3131,13 @@
                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
                     break;
                 case R.styleable.View_textDirection:
-                    mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
+                    // Clear any text direction flag already set
+                    mPrivateFlags2 &= ~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];
+                    }
                     break;
             }
         }
@@ -14491,8 +14518,16 @@
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE},
      */
+    @ViewDebug.ExportedProperty(category = "text", mapping = {
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
+    })
     public int getTextDirection() {
-        return mTextDirection;
+        return (mPrivateFlags2 & TEXT_DIRECTION_MASK) >> TEXT_DIRECTION_MASK_SHIFT;
     }
 
     /**
@@ -14508,9 +14543,14 @@
      * {@link #TEXT_DIRECTION_LOCALE},
      */
     public void setTextDirection(int textDirection) {
-        if (textDirection != mTextDirection) {
-            mTextDirection = textDirection;
+        if (getTextDirection() != textDirection) {
+            // Reset the current text direction
+            mPrivateFlags2 &= ~TEXT_DIRECTION_MASK;
+            // Set the new text direction
+            mPrivateFlags2 |= ((textDirection << TEXT_DIRECTION_MASK_SHIFT) & TEXT_DIRECTION_MASK);
+            // Reset the current resolved text direction
             resetResolvedTextDirection();
+            // Ask for a layout pass
             requestLayout();
         }
     }
@@ -14518,7 +14558,12 @@
     /**
      * Return the resolved text direction.
      *
-     * @return the resolved text direction. Return one of:
+     * This needs resolution if the value is TEXT_DIRECTION_INHERIT. The resolution matches
+     * {@link #getTextDirection()}if it is not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds
+     * up the parent chain of the view. if there is no parent, then it will return the default
+     * {@link #TEXT_DIRECTION_FIRST_STRONG}.
+     *
+     * @return the resolved text direction. Returns one of:
      *
      * {@link #TEXT_DIRECTION_FIRST_STRONG}
      * {@link #TEXT_DIRECTION_ANY_RTL},
@@ -14527,10 +14572,11 @@
      * {@link #TEXT_DIRECTION_LOCALE},
      */
     public int getResolvedTextDirection() {
-        if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) {
+        // The text direction is not inherited so return it back
+        if ((mPrivateFlags2 & TEXT_DIRECTION_RESOLVED) != TEXT_DIRECTION_RESOLVED) {
             resolveTextDirection();
         }
-        return mResolvedTextDirection;
+        return (mPrivateFlags2 & TEXT_DIRECTION_RESOLVED_MASK) >> TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
     }
 
     /**
@@ -14538,17 +14584,51 @@
      * resolution is done.
      */
     public void resolveTextDirection() {
-        if (mResolvedTextDirection != TEXT_DIRECTION_INHERIT) {
-            // Resolution has already been done.
-            return;
+        // Reset any previous text direction resolution
+        mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
+
+        // Set resolved text direction flag depending on text direction flag
+        final int textDirection = getTextDirection();
+        switch(textDirection) {
+            case TEXT_DIRECTION_INHERIT:
+                if (canResolveTextDirection()) {
+                    ViewGroup viewGroup = ((ViewGroup) mParent);
+
+                    // Set current resolved direction to the same value as the parent's one
+                    final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
+                    switch (parentResolvedDirection) {
+                        case TEXT_DIRECTION_FIRST_STRONG:
+                        case TEXT_DIRECTION_ANY_RTL:
+                        case TEXT_DIRECTION_LTR:
+                        case TEXT_DIRECTION_RTL:
+                        case TEXT_DIRECTION_LOCALE:
+                            mPrivateFlags2 |=
+                                    (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                            break;
+                        default:
+                            // Default resolved direction is "first strong" heuristic
+                            mPrivateFlags2 |= 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;
+                }
+                break;
+            case TEXT_DIRECTION_FIRST_STRONG:
+            case TEXT_DIRECTION_ANY_RTL:
+            case TEXT_DIRECTION_LTR:
+            case TEXT_DIRECTION_RTL:
+            case TEXT_DIRECTION_LOCALE:
+                // Resolved direction is the same as text direction
+                mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                break;
+            default:
+                // Default resolved direction is "first strong" heuristic
+                mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
         }
-        if (mTextDirection != TEXT_DIRECTION_INHERIT) {
-            mResolvedTextDirection = mTextDirection;
-        } else if (mParent != null && mParent instanceof ViewGroup) {
-            mResolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
-        } else {
-            mResolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG;
-        }
+
+        // Set to resolved
+        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED;
         onResolvedTextDirectionChanged();
     }
 
@@ -14562,12 +14642,26 @@
     }
 
     /**
+     * Check if text direction resolution can be done.
+     *
+     * @return true if text direction resolution can be done otherwise return false.
+     */
+    public boolean canResolveTextDirection() {
+        switch (getTextDirection()) {
+            case TEXT_DIRECTION_INHERIT:
+                return (mParent != null) && (mParent instanceof ViewGroup);
+            default:
+                return true;
+        }
+    }
+
+    /**
      * Reset resolved text direction. Text direction can be resolved with a call to
      * getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
      * reset is done.
      */
     public void resetResolvedTextDirection() {
-        mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
+        mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
         onResolvedTextDirectionReset();
     }
 
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index dc8c71b7..d92ebcd 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -875,7 +875,7 @@
      * otherwise.
      *
      * @param currentTime Where we are in the animation. This is wall clock time.
-     * @param outTransformation A tranformation object that is provided by the
+     * @param outTransformation A transformation object that is provided by the
      *        caller and will be filled in by the animation.
      * @param scale Scaling factor to apply to any inputs to the transform operation, such
      *        pivot points being rotated or scaled around.
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index cf210c8..e8c1d23 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -112,6 +112,16 @@
     }
     
     /**
+     * Like {@link #compose(Transformation)} but does this.postConcat(t) of
+     * the transformation matrix.
+     * @hide
+     */
+    public void postCompose(Transformation t) {
+        mAlpha *= t.getAlpha();
+        mMatrix.postConcat(t.getMatrix());
+    }
+
+    /**
      * @return The 3x3 Matrix representing the trnasformation to apply to the
      * coordinates of the object being animated
      */
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 0e5ff20..17dbde8 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -403,6 +403,9 @@
                                 mIInputContext.finishComposingText();
                             } catch (RemoteException e) {
                             }
+                            // Check focus again in case that "onWindowFocus" is called before
+                            // handling this message.
+                            checkFocus(mHasBeenInactive);
                         }
                     }
                     return;
@@ -1173,13 +1176,17 @@
         }
     }
 
+    private void checkFocus(boolean forceNewFocus) {
+        if (checkFocusNoStartInput(forceNewFocus)) {
+            startInputInner(null, 0, 0, 0);
+        }
+    }
+
     /**
      * @hide
      */
     public void checkFocus() {
-        if (checkFocusNoStartInput(false)) {
-            startInputInner(null, 0, 0, 0);
-        }
+        checkFocus(false);
     }
 
     private boolean checkFocusNoStartInput(boolean forceNewFocus) {
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 757a619..6c35f19 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -144,7 +144,6 @@
                         null);
             }
         }
-        mDatabase.enableWriteAheadLogging();
 
         // mDatabase should not be null,
         // the only case is RequestAPI test has problem to create db
@@ -163,11 +162,6 @@
                 mDatabase.endTransaction();
             }
         }
-
-        // use per table Mutex lock, turn off database lock, this
-        // improves performance as database's ReentrantLock is
-        // expansive
-        mDatabase.setLockingEnabled(false);
     }
 
     private static void upgradeDatabase() {
diff --git a/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java b/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java
index ef7e651..3d46cdd 100644
--- a/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java
+++ b/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java
@@ -123,7 +123,7 @@
     private OnClickListener mSwitchOldListener = new OnClickListener() {
         public void onClick(View v) {
             try {
-                ActivityManagerNative.getDefault().moveTaskToFront(mCurTask, 0);
+                ActivityManagerNative.getDefault().moveTaskToFront(mCurTask, 0, null);
             } catch (RemoteException e) {
             }
             finish();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0563846..af722a8 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -33,14 +33,17 @@
 import android.os.Bundle;
 import android.os.PatternMatcher;
 import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
+import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
 import android.widget.ImageView;
+import android.widget.ListView;
 import android.widget.TextView;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
@@ -122,6 +125,11 @@
         }
 
         setupAlert();
+
+        ListView lv = mAlert.getListView();
+        if (lv != null) {
+            lv.setOnItemLongClickListener(new ItemLongClickListener());
+        }
     }
 
     @Override
@@ -489,5 +497,18 @@
             mClearDefaultHint.setVisibility(View.GONE);
         }
     }
+
+    class ItemLongClickListener implements AdapterView.OnItemLongClickListener {
+
+        @Override
+        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+            ResolveInfo ri = mAdapter.resolveInfoForPosition(position);
+            Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
+                    .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
+            startActivity(in);
+            return true;
+        }
+
+    }
 }
 
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index afbcfc2..8d6fab4 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -20,8 +20,8 @@
 #include <android_runtime/AndroidRuntime.h>
 
 #include <utils/Log.h>
+#include <utils/ZipFileRO.h>
 #include <ScopedUtfChars.h>
-#include <androidfw/ZipFileRO.h>
 
 #include <zlib.h>
 
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index fd32c8e..f020f5d 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Voeg rekening by"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Verhoging"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Verminder"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> raak en hou."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Skuif op om by te tel en af om af te trek."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Tel \'n minuut by"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Trek \'n minuut af"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 50b6c67..f1379f7 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"መለያ አክል"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"ጨምር"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"ቀንስ"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> ንካ እና ያዝ።"</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"ለመጨመር ወደላይ ለመቀነስ ወደታች አንሸራት"</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"ደቂቃዎች ጨምር"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"ደቂቃ ቀንስ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9bd3ab2..a156e64 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"إضافة حساب"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"زيادة"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"تناقص"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> المس مع الاستمرار."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"مرر لأعلى للزيادة ولأسفل للإنقاص."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"زيادة دقيقة"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"إنقاص دقيقة"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 2526bcd..0178764 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Дадаць уліковы запіс"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Інкрэмент"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Дэкрэмент"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Націсніце і ўтрымлівайце <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Перасуньце палец уверх, каб павялiчыць адрэзак, або ўніз, каб паменшыць."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"На хвiлiну больш"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"На хвiлiну менш"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index b34de19..479e118 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Добавяне на профил"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Увеличаване"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Намаляване"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Докоснете <xliff:g id="VALUE">%s</xliff:g> път/и и задръжте."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Плъзнете нагоре за увеличаване и надолу за намаляване."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Увеличаване на минутите"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Намаляване на минутите"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 675a4ba..64d0f87 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Afegeix un compte"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Incrementa"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Disminueix"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén premut <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Fes lliscar el dit cap amunt per incrementar i cap avall per disminuir."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Incrementa els minuts"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Disminueix els minuts"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b11f852..d2a4cc1 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -916,8 +916,8 @@
     <string name="no" msgid="5141531044935541497">"Zrušit"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Upozornění"</string>
     <string name="loading" msgid="7933681260296021180">"Načítání..."</string>
-    <string name="capital_on" msgid="1544682755514494298">"ZAPNUTO"</string>
-    <string name="capital_off" msgid="6815870386972805832">"VYPNUTO"</string>
+    <string name="capital_on" msgid="1544682755514494298">"I"</string>
+    <string name="capital_off" msgid="6815870386972805832">"O"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Dokončit akci pomocí aplikace"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Použít jako výchozí nastavení pro tuto činnost."</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Výchozí nastavení vymažete v části Nastavení systému &gt; Aplikace &gt; Stažené."</string>
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Přidat účet"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Zvýšení"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Snížení"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> dotkněte se a podržte."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Chcete-li přičítat, přejeďte prstem nahoru, chcete-li odečítat, přejeďte prstem dolů."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Přičíst minutu"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Odečíst minutu"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 89f3451..b139e5e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Tilføj konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Optælling"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Nedtælling"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Tryk <xliff:g id="VALUE">%s</xliff:g> gange, og hold inde."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Glid op for at tilføje, og glid ned for at fjerne."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Tilføj minut"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Fjern minut"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 2de5212..baf3e40 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Konto hinzufügen"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Erhöhen"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Verringern"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> berühren und gedrückt halten"</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Zum Vorstellen nach oben und zum Zurückstellen nach unten ziehen"</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minute vorstellen"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minute zurückstellen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 4906812..ad840e3 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Προσθήκη λογαριασμού"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Αύξηση"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Μείωση"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Πατήστε παρατεταμένα το <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Πραγματοποιήστε κύλιση προς τα πάνω για αύξηση και προς τα κάτω για μείωση."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Αύξηση λεπτού"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Μείωση λεπτού"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index d8dac7c..de92665 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Add account"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Increment"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decrement"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> touch and hold."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Slide up to increment and down to decrease."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Increment minute"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Decrement minute"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 0071e0a..8761ca9 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Agregar una cuenta"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Incremento"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decremento"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén presionado <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Deslízate hacia arriba para aumentar y hacia abajo para disminuir."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumentar minutos"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Disminuir minutos"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 05b837d..9ede6a0 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Añadir cuenta"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumentar"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Disminuir"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén pulsado <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Desliza el dedo hacia arriba para aumentar y hacia abajo para disminuir."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumentar minuto"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Disminuir minuto"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 22de35d..b68944e 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Lisa konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Suurenda"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Vähenda"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> puudutage ja hoidke."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Suurendamiseks lohistage üles, vähendamiseks alla."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minutite arvu suurendamine"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minutite arvu vähendamine"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index dd6a016..7ee47e7 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"افزودن حساب"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"افزایش"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"کاهش"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> لمس کرده و نگه دارید."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"برای افزایش به بالا و برای کاهش به پایین بلغزانید."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">" افزایش دقیقه"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"کاهش دقیقه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c744479..b1009a5 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Lisää tili"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Lisää"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Vähennä"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> kosketa pitkään."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Kasvata tai pienennä arvoa liu\'uttamalla ylös tai alas."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Kasvata minuuttia"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Pienennä minuuttia"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 62fe768..d044a70 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Ajouter un compte"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Augmenter"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuer"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> appuyez de manière prolongée."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Faire glisser vers le haut pour augmenter et vers le bas pour diminuer"</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minute suivante"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minute précédente"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index bfc2f71..bd8863f 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"खाता जोड़ें"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"वृद्धि"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"कमी"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> को स्‍पर्श करके रखें."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"बढ़ते क्रम के लिए ऊपर और घटते क्रम के लिए नीचे की ओर स्‍लाइड करें."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"बढ़ते क्रम में मिनट"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"घटते क्रम में मिनट"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 77c5a10..749012b 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj račun"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Povećaj"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Smanji"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> pritisnite i držite."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Klizite prema gore za pomak unaprijed, a prema dolje za pomak unatrag."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Pomak unaprijed za jednu minutu"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Pomak unatrag za jednu minutu"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 466cb3a..24a70d7 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Fiók hozzáadása"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Növelés"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Csökkentés"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> érintse meg és tartsa lenyomva."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Csúsztassa fel a növeléshez és le a csökkentéshez."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Percek növelése"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Percek csökkentése"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 2ad73a4..8384b48 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Tambahkan akun"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Penambahan"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Pengurangan"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> sentuh dan tahan."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Geser ke atas untuk menambah dan ke bawah untuk mengurangi."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Menit penambahan"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Menit pengurangan"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 1eb3be4..75ed4e8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Aggiungi account"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumenta"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuisci"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Tocca e tieni premuto il numero <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Scorri verso l\'alto per aumentare il valore e verso il basso per diminuirlo."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumenta minuto"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Diminuisci minuto"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 8edf115..f51f232 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"הוסף חשבון"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"הגדל"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"הפחת"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> גע והחזק."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"הסט מעלה כדי להוסיף ומטה כדי להפחית."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"הוסף דקה"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"הפחת דקה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index fba0304..549c1e2 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"アカウントを追加"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"増やす"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"減らす"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g>回タップして押し続けます。"</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"上にスライドで大きく、下にスライドで小さくなります。"</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"1分進める"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"1分戻す"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 211c79c..fc8e7b1 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"계정 추가"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"올리기"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"줄이기"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> 길게 터치하세요."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"올리려면 위로 슬라이드하고 줄이려면 아래로 슬라이드합니다."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"\'분\'을 올립니다."</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"\'분\'을 줄입니다."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 9ceaa1d..5e9d3f4 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Pridėti paskyrą"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Padidinti"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Sumažinti"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Palieskite <xliff:g id="VALUE">%s</xliff:g> ir laikykite."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Slinkite aukštyn, kad būtų parodytas padidėjimas, ir žemyn, kad būtų parodytas sumažėjimas."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Padidėjimo minutė"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Sumažėjimo minutė"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 6ebc733..a568c3b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Pievienot kontu"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Palielināt"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Samazināt"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g>: pieskarieties un turiet nospiestu."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Bīdiet uz augšu, lai palielinātu vērtību, un uz leju, lai to samazinātu."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Palielināt minūtes vērtību"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Samazināt minūtes vērtību"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 2b7fc36..363832d 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Tambah akaun"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Kenaikan"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Penyusutan"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> sentuh terus."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Luncurkan ke atas untuk kenaikan dan ke bawah untuk penyusutan."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minit kenaikan"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minit penyusutan"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 580d30c..384fdac 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Legg til konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Øke"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Senke"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> – trykk og hold inne."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Skyv opp for å øke og ned for å redusere."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Endre minutter (fremover)"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Endre minutter (bakover)"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 010a4d8..030222d 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Account toevoegen"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Hoger"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Lager"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> blijven aanraken."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Schuif omhoog om te verhogen en omlaag om te verlagen."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minuten verhogen"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minuten verlagen"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 3d58076..9e4cbf3 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Zwiększ"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zmniejsz"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> dotknij i przytrzymaj."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Przesuń w górę, aby zwiększyć wartość, lub w dół, aby ją zmniejszyć."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Następna minuta"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Poprzednia minuta"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3e4c31b..abe1454 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Adicionar conta"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumentar"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuir"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Toque sem soltar em <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Deslize lentamente para cima para aumentar e para baixo para diminuir."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumentar minuto"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Diminuir minuto"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 0af0052..3ae566c 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Adicionar conta"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Incremento"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Redução"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> toque e mantenha pressionado."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Deslize para cima para aumentar e para baixo para diminuir."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumentar minuto"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Diminuir minuto"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index f14b247..fc6a510 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1746,6 +1746,8 @@
     <skip />
     <!-- no translation found for number_picker_decrement_button (2576606679160067262) -->
     <skip />
+    <!-- no translation found for number_picker_increment_scroll_mode (3073101067441638428) -->
+    <skip />
     <!-- no translation found for number_picker_increment_scroll_action (4628981789985093179) -->
     <skip />
     <!-- no translation found for time_picker_increment_minute_button (2843066823236250329) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 32d25c1..d443d1d 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Adăugaţi un cont"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Incrementaţi"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decrementaţi"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Atingeţi şi ţineţi apăsat <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Glisaţi în sus pentru incrementare şi în jos pentru decrementare."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Incrementaţi valoarea pentru minut"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Decrementaţi valoarea pentru minut"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 989be4a..5ed4c2e 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Добавить аккаунт"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Увеличить"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Уменьшить"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Нажмите и удерживайте <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Проведите вверх, чтобы увеличить значение, и вниз, чтобы уменьшить его."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"На минуту вперед"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"На минуту назад"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 4a1fe20..2e97b82 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Pridať účet"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Zvýšenie"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zníženie"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Dotknite sa a podržte <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Ak chcete pripočítať, potiahnite prst nahor. Ak chcete odpočítať, potiahnite prst nadol."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Pripočítať minútu"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Odpočítať minútu"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e079147..f66cabb 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj račun"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Povečaj"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zmanjšaj"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Dotaknite se vrednosti <xliff:g id="VALUE">%s</xliff:g> in jo pridržite."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Povlecite gor za povečanje in dol za zmanjšanje."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Povečaj minute"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Zmanjšaj minute"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 273a3ac..66c0561 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Додај налог"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Повећање"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Смањење"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> додирните и задржите."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Превуците нагоре за повећање, а надоле за смањење."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Повећај минуте"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Смањи минуте"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 291f36b..6559fc5 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -743,8 +743,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tips! Dubbelknacka om du vill zooma in eller ut."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autofyll"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Ange Autofyll"</string>
-    <!-- no translation found for autofill_address_name_separator (6350145154779706772) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -1169,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Lägg till konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Öka"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Minska"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> tryck länge."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Skjut uppåt för att öka och nedåt för att minska."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Öka minuter"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minska minuter"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index dfdeb2f..39d2aba 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Ongeza akaunti"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Ongezeko"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Punguza"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> gusa na ushikilie."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Nyiririsha juu kuongeza na chini kupunguza."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Dakika ya nyongeza"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Dakika pungufu"</string>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 7fa7658..49c8893 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -21,7 +21,7 @@
      for different hardware and product builds. -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- see comment in values/config.xml -->
-    <integer name="config_longPressOnPowerBehavior">2</integer>
+    <integer name="config_longPressOnPowerBehavior">1</integer>
 
     <!-- Enable lockscreen rotation -->
     <bool name="config_enableLockScreenRotation">true</bool>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ebd2a31..4b59923 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"เพิ่มบัญชี"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"การเพิ่ม"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"การลด"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"แตะ <xliff:g id="VALUE">%s</xliff:g> ค้างไว้"</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"เลื่อนขึ้นเพื่อเพิ่มและเลื่อนลงเพื่อลด"</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"เพิ่มนาที"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"ลดนาที"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 0cc2b1f..dc22a08 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Magdagdag ng account"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Taasan"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Babaan"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> pindutin nang matagal."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"I-slide pataas upang magdagdag at pababa upang magbawas."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minuto ng pagdaragdag"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minuto ng pagbawas"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index c4a5e83..419ae96 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Hesap ekle"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Artır"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Azalt"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> rakamına dokunun ve basılı tutun."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Artırmak için yukarı, azaltmak için aşağı kaydırın."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Dakika değerini artır"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Dakika değerini azalt"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index ac04bc2..13311f1 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Додати облік. запис"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Додати"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Відняти"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> – торкніться й утримуйте."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Перемістіть угору, щоб додати, і вниз, щоб відняти."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Додати хвилину"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Відняти хвилину"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7fa924b..b94f104 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Thêm tài khoản"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Tăng dần"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Giảm dần"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Chạm và giữ <xliff:g id="VALUE">%s</xliff:g>."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Trượt lên để tăng và trượt xuống để giảm."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Phút tăng dần"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Phút giảm dần"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 53baaef..d7a1e43 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -145,7 +145,7 @@
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"您的手机会关机。"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"您要关机吗?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"近期任务"</string>
-    <string name="no_recent_tasks" msgid="8794906658732193473">"最近没有运行任何应用程序"</string>
+    <string name="no_recent_tasks" msgid="8794906658732193473">"最近没有运行任何应用"</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"平板电脑选项"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"手机选项"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"屏幕锁定"</string>
@@ -179,162 +179,162 @@
     <string name="permgrouplab_systemTools" msgid="4652191644082714048">"系统工具"</string>
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"对系统进行低级访问和控制。"</string>
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"开发工具"</string>
-    <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"只有应用程序开发人员才需要的功能。"</string>
+    <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"只有应用开发人员才需要的功能。"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"存储"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"访问 USB 存储设备。"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"访问 SD 卡。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改状态栏"</string>
-    <string name="permdesc_statusBar" msgid="8434669549504290975">"允许应用程序停用状态栏或者增删系统图标。"</string>
+    <string name="permdesc_statusBar" msgid="8434669549504290975">"允许应用停用状态栏或者增删系统图标。"</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"状态栏"</string>
-    <string name="permdesc_statusBarService" msgid="716113660795976060">"允许以状态栏形式显示应用程序。"</string>
+    <string name="permdesc_statusBarService" msgid="716113660795976060">"允许以状态栏形式显示应用。"</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"展开/收拢状态栏"</string>
-    <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"允许应用程序展开或折叠状态栏。"</string>
+    <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"允许应用展开或折叠状态栏。"</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"拦截外拨电话"</string>
-    <string name="permdesc_processOutgoingCalls" msgid="1152111671618301044">"允许应用程序处理外拨通话并更改要拨打的号码。恶意应用程序可能会监视、重定向或阻止外拨通话。"</string>
+    <string name="permdesc_processOutgoingCalls" msgid="1152111671618301044">"允许应用处理外拨通话并更改要拨打的号码。恶意应用可能会监视、重定向或阻止外拨通话。"</string>
     <string name="permlab_receiveSms" msgid="2697628268086208535">"接收短信"</string>
-    <string name="permdesc_receiveSms" msgid="8107887121893611793">"允许应用程序接收和处理短信。恶意应用程序可能会监视您的短信,或删除短信而不向您显示。"</string>
+    <string name="permdesc_receiveSms" msgid="8107887121893611793">"允许应用接收和处理短信。恶意应用可能会监视您的短信,或删除短信而不向您显示。"</string>
     <string name="permlab_receiveMms" msgid="8894700916188083287">"接收彩信"</string>
-    <string name="permdesc_receiveMms" msgid="1424805308566612086">"允许应用程序接收和处理彩信。恶意应用程序可能会监视您的短信,或删除短信而不向您显示。"</string>
+    <string name="permdesc_receiveMms" msgid="1424805308566612086">"允许应用接收和处理彩信。恶意应用可能会监视您的短信,或删除短信而不向您显示。"</string>
     <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"接收紧急广播"</string>
-    <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"允许应用程序接收和处理紧急广播消息。此权限仅适用于系统应用程序。"</string>
+    <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"允许应用接收和处理紧急广播消息。此权限仅适用于系统应用。"</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"发送短信"</string>
-    <string name="permdesc_sendSms" msgid="906546667507626156">"允许应用程序发送短信。恶意应用程序可能会未经您的确认而发送短信,由此产生相关费用。"</string>
+    <string name="permdesc_sendSms" msgid="906546667507626156">"允许应用发送短信。恶意应用可能会未经您的确认而发送短信,由此产生相关费用。"</string>
     <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"不经确认直接发送短信"</string>
-    <string name="permdesc_sendSmsNoConfirmation" msgid="3437759207020400204">"允许应用程序发送短信。恶意应用程序可能会未经您的确认而发送短信,由此产生相关费用。"</string>
+    <string name="permdesc_sendSmsNoConfirmation" msgid="3437759207020400204">"允许应用发送短信。恶意应用可能会未经您的确认而发送短信,由此产生相关费用。"</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"读取短信或彩信"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="2341692916884515613">"允许应用程序读取您的平板电脑或 SIM 卡上存储的短信。恶意应用程序可能会读取您的机密短信。"</string>
-    <string name="permdesc_readSms" product="default" msgid="5653850482025875493">"允许应用程序读取您的手机或 SIM 卡上存储的短信。恶意应用程序可能借此读取您的机密短信。"</string>
+    <string name="permdesc_readSms" product="tablet" msgid="2341692916884515613">"允许应用读取您的平板电脑或 SIM 卡上存储的短信。恶意应用可能会读取您的机密短信。"</string>
+    <string name="permdesc_readSms" product="default" msgid="5653850482025875493">"允许应用读取您的手机或 SIM 卡上存储的短信。恶意应用可能借此读取您的机密短信。"</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"编辑短信或彩信"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"允许应用程序对平板电脑或 SIM 卡上存储的短信执行写入操作。恶意应用程序可能会删除您的短信。"</string>
-    <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"允许应用程序对手机或 SIM 卡上存储的短信执行写入操作。恶意应用程序可能会删除您的短信。"</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"允许应用对平板电脑或 SIM 卡上存储的短信执行写入操作。恶意应用可能会删除您的短信。"</string>
+    <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"允许应用对手机或 SIM 卡上存储的短信执行写入操作。恶意应用可能会删除您的短信。"</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"接收 WAP"</string>
-    <string name="permdesc_receiveWapPush" msgid="7983455145335316872">"允许应用程序接收和处理 WAP 短信。恶意应用程序可能会监视您的短信,或删除短信而不向您显示。"</string>
-    <string name="permlab_getTasks" msgid="6466095396623933906">"检索正在运行的应用程序"</string>
-    <string name="permdesc_getTasks" msgid="6608159250520381359">"允许应用程序针对近期运行的和当前正在运行的任务检索相关信息。恶意应用程序可能会发现有关其他应用程序的私密信息。"</string>
-    <string name="permlab_reorderTasks" msgid="2018575526934422779">"对正在运行的应用程序重新排序"</string>
-    <string name="permdesc_reorderTasks" msgid="4175137612205663399">"允许应用程序将任务移动到前台和后台。恶意应用程序可能会不受您的控制,强行让自己处于前台。"</string>
-    <string name="permlab_removeTasks" msgid="6821513401870377403">"停止正在运行的应用程序"</string>
-    <string name="permdesc_removeTasks" msgid="1394714352062635493">"允许该应用程序删除任务并终止这些任务的应用程序。恶意应用程序可以籍此影响其他应用程序的行为。"</string>
+    <string name="permdesc_receiveWapPush" msgid="7983455145335316872">"允许应用接收和处理 WAP 短信。恶意应用可能会监视您的短信,或删除短信而不向您显示。"</string>
+    <string name="permlab_getTasks" msgid="6466095396623933906">"检索正在运行的应用"</string>
+    <string name="permdesc_getTasks" msgid="6608159250520381359">"允许应用针对近期运行的和当前正在运行的任务检索相关信息。恶意应用可能会发现有关其他应用的私密信息。"</string>
+    <string name="permlab_reorderTasks" msgid="2018575526934422779">"对正在运行的应用重新排序"</string>
+    <string name="permdesc_reorderTasks" msgid="4175137612205663399">"允许应用将任务移动到前台和后台。恶意应用可能会不受您的控制,强行让自己处于前台。"</string>
+    <string name="permlab_removeTasks" msgid="6821513401870377403">"停止正在运行的应用"</string>
+    <string name="permdesc_removeTasks" msgid="1394714352062635493">"允许该应用删除任务并终止这些任务的应用。恶意应用可以籍此影响其他应用的行为。"</string>
     <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"设置屏幕兼容性"</string>
-    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"允许该应用程序控制其他应用程序的屏幕兼容模式。恶意应用程序可以籍此影响其他应用程序的行为。"</string>
-    <string name="permlab_setDebugApp" msgid="3022107198686584052">"启用应用程序调试"</string>
-    <string name="permdesc_setDebugApp" msgid="4474512416299013256">"允许该应用程序对其他应用程序启用调试。恶意应用程序可以籍此终止其他的应用程序。"</string>
+    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"允许该应用控制其他应用的屏幕兼容模式。恶意应用可以籍此影响其他应用的行为。"</string>
+    <string name="permlab_setDebugApp" msgid="3022107198686584052">"启用应用调试"</string>
+    <string name="permdesc_setDebugApp" msgid="4474512416299013256">"允许该应用对其他应用启用调试。恶意应用可以籍此终止其他的应用。"</string>
     <string name="permlab_changeConfiguration" msgid="8214475779521218295">"更改用户界面设置"</string>
-    <string name="permdesc_changeConfiguration" msgid="4372223873154296076">"允许该应用程序更改当前配置,例如语言区域或整体的字体大小。"</string>
+    <string name="permdesc_changeConfiguration" msgid="4372223873154296076">"允许该应用更改当前配置,例如语言区域或整体的字体大小。"</string>
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"启用车载模式"</string>
-    <string name="permdesc_enableCarMode" msgid="4853187425751419467">"允许应用程序启用车载模式。"</string>
+    <string name="permdesc_enableCarMode" msgid="4853187425751419467">"允许应用启用车载模式。"</string>
     <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"结束后台进程"</string>
-    <string name="permdesc_killBackgroundProcesses" msgid="931129103262126617">"允许应用程序在内存空间充足的情况下终止其他应用程序的后台进程。"</string>
-    <string name="permlab_forceStopPackages" msgid="2329627428832067700">"强行停止其他应用程序"</string>
-    <string name="permdesc_forceStopPackages" msgid="5253157296183940812">"允许应用程序强行停止其他应用程序。"</string>
-    <string name="permlab_forceBack" msgid="652935204072584616">"强制应用程序关闭"</string>
-    <string name="permdesc_forceBack" msgid="3892295830419513623">"允许应用程序强制关闭任何前台活动并返回。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_killBackgroundProcesses" msgid="931129103262126617">"允许应用在内存空间充足的情况下终止其他应用的后台进程。"</string>
+    <string name="permlab_forceStopPackages" msgid="2329627428832067700">"强行停止其他应用"</string>
+    <string name="permdesc_forceStopPackages" msgid="5253157296183940812">"允许应用强行停止其他应用。"</string>
+    <string name="permlab_forceBack" msgid="652935204072584616">"强制应用关闭"</string>
+    <string name="permdesc_forceBack" msgid="3892295830419513623">"允许应用强制关闭任何前台活动并返回。普通应用绝不需要此权限。"</string>
     <string name="permlab_dump" msgid="1681799862438954752">"检索系统内部状态"</string>
-    <string name="permdesc_dump" msgid="1778299088692290329">"允许应用程序检索系统的内部状态。恶意应用程序可能会检索一般情况下绝不需要检索的多种私人信息和安全信息。"</string>
+    <string name="permdesc_dump" msgid="1778299088692290329">"允许应用检索系统的内部状态。恶意应用可能会检索一般情况下绝不需要检索的多种私人信息和安全信息。"</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"检索屏幕内容"</string>
-    <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允许应用程序检索活动窗口的内容。恶意应用程序可能会检索整个窗口的内容,并检查其中除密码以外的所有文字。"</string>
+    <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允许应用检索活动窗口的内容。恶意应用可能会检索整个窗口的内容,并检查其中除密码以外的所有文字。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分关机"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string>
-    <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用程序"</string>
-    <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"阻止用户切换到其他应用程序。"</string>
-    <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"监控所有应用程序的启动"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"允许应用程序监视和控制系统是如何启动活动的。恶意应用程序可能会完全破坏系统。此权限只有在进行开发时才需要,正常使用情况下绝不需要。"</string>
+    <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用"</string>
+    <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"阻止用户切换到其他应用。"</string>
+    <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"监控所有应用的启动"</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"允许应用监视和控制系统是如何启动活动的。恶意应用可能会完全破坏系统。此权限只有在进行开发时才需要,正常使用情况下绝不需要。"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"发送包删除的广播"</string>
-    <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"允许应用程序广播一条有关已删除了应用程序包的通知。恶意应用程序可能借此终止其他任何正在运行的应用程序。"</string>
+    <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"允许应用广播一条有关已删除了应用包的通知。恶意应用可能借此终止其他任何正在运行的应用。"</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"发送短信收到的广播"</string>
-    <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"允许应用程序广播一条有关已收到短信的通知。恶意应用程序可能借此伪造接到的短信。"</string>
+    <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"允许应用广播一条有关已收到短信的通知。恶意应用可能借此伪造接到的短信。"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"发送 WAP-PUSH 收到的广播"</string>
-    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"允许应用程序广播一条有关已收到 WAP PUSH 短信的通知。恶意应用程序可能借此伪造短信接收,或在后台将任意网页的内容替换为恶意内容。"</string>
+    <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"允许应用广播一条有关已收到 WAP PUSH 短信的通知。恶意应用可能借此伪造短信接收,或在后台将任意网页的内容替换为恶意内容。"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"限制运行的进程个数"</string>
-    <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允许应用程序控制将运行的进程数上限。普通应用程序绝不需要此权限。"</string>
-    <string name="permlab_setAlwaysFinish" msgid="238828158465736054">"关闭所有后台应用程序"</string>
-    <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"允许应用程序控制活动在转入后台后是否立即结束。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允许应用控制将运行的进程数上限。普通应用绝不需要此权限。"</string>
+    <string name="permlab_setAlwaysFinish" msgid="238828158465736054">"关闭所有后台应用"</string>
+    <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"允许应用控制活动在转入后台后是否立即结束。普通应用绝不需要此权限。"</string>
     <string name="permlab_batteryStats" msgid="7863923071360031652">"修改电池统计信息"</string>
-    <string name="permdesc_batteryStats" msgid="6835186932305744068">"允许应用程序修改收集到的电池统计信息。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_batteryStats" msgid="6835186932305744068">"允许应用修改收集到的电池统计信息。普通应用不能使用此权限。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"控制系统备份和还原"</string>
-    <string name="permdesc_backup" msgid="6912230525140589891">"允许应用程序控制系统的备份和还原机制。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_backup" msgid="6912230525140589891">"允许应用控制系统的备份和还原机制。普通应用不能使用此权限。"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"确认完整备份或恢复操作"</string>
-    <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"允许应用程序启动完整备份确认用户界面。不用于任何应用程序。"</string>
+    <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"允许应用启动完整备份确认用户界面。不用于任何应用。"</string>
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"显示未授权的窗口"</string>
-    <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"允许该应用程序创建供内部系统用户界面使用的窗口。普通应用程序不应使用此权限。"</string>
+    <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"允许该应用创建供内部系统用户界面使用的窗口。普通应用不应使用此权限。"</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"显示系统级警报"</string>
-    <string name="permdesc_systemAlertWindow" msgid="8507863469978066409">"允许应用程序显示系统警告窗口。恶意应用程序可能会控制整个屏幕。"</string>
+    <string name="permdesc_systemAlertWindow" msgid="8507863469978066409">"允许应用显示系统警告窗口。恶意应用可能会控制整个屏幕。"</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"修改全局动画速度"</string>
-    <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"允许该应用程序随时更改全局动画速度(加快或减慢)。"</string>
-    <string name="permlab_manageAppTokens" msgid="1286505717050121370">"管理应用程序令牌"</string>
-    <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"允许应用程序绕过其正常的 Z 排序创建和管理自己的令牌。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"允许该应用随时更改全局动画速度(加快或减慢)。"</string>
+    <string name="permlab_manageAppTokens" msgid="1286505717050121370">"管理应用令牌"</string>
+    <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"允许应用绕过其正常的 Z 排序创建和管理自己的令牌。普通应用绝不需要此权限。"</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"按键和控制按钮"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"允许应用程序将自身的输入活动(例如按键操作等)提供给其他应用程序。恶意应用程序可能借此控制平板电脑。"</string>
-    <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"允许应用程序将自身的输入活动(例如按键操作等)提供给其他应用程序。恶意应用程序可能借此控制手机。"</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"允许应用将自身的输入活动(例如按键操作等)提供给其他应用。恶意应用可能借此控制平板电脑。"</string>
+    <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"允许应用将自身的输入活动(例如按键操作等)提供给其他应用。恶意应用可能借此控制手机。"</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"记录您键入的内容和执行的操作"</string>
-    <string name="permdesc_readInputState" msgid="8387754901688728043">"允许应用程序记录您所按的键,包括与其他应用程序进行交互(如输入密码)时按的键。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_readInputState" msgid="8387754901688728043">"允许应用记录您所按的键,包括与其他应用进行交互(如输入密码)时按的键。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"绑定至输入法"</string>
-    <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"允许用户绑定至输入法的顶级接口。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"允许用户绑定至输入法的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindTextService" msgid="7358378401915287938">"绑定至文字服务"</string>
-    <string name="permdesc_bindTextService" msgid="8151968910973998670">"允许用户绑定至文字服务(如 SpellCheckerService)的顶级接口。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_bindTextService" msgid="8151968910973998670">"允许用户绑定至文字服务(如 SpellCheckerService)的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindVpnService" msgid="4708596021161473255">"绑定到 VPN 服务"</string>
-    <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允许用户绑定到 VPN 服务的顶级接口。普通应用程序从不需要此权限。"</string>
+    <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允许用户绑定到 VPN 服务的顶级接口。普通应用从不需要此权限。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"绑定到壁纸"</string>
-    <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允许用户绑定到壁纸的顶级接口。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允许用户绑定到壁纸的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到窗口小部件服务"</string>
-    <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允许用户绑定到窗口小部件服务的顶级接口。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允许用户绑定到窗口小部件服务的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"与设备管理器交互"</string>
-    <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允许用户将意向发送给设备管理员。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允许用户将意向发送给设备管理员。普通应用绝不需要此权限。"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕显示方向"</string>
-    <string name="permdesc_setOrientation" msgid="3046126619316671476">"允许应用程序随时更改屏幕的旋转状态。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_setOrientation" msgid="3046126619316671476">"允许应用随时更改屏幕的旋转状态。普通应用绝不需要此权限。"</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"更改指针速度"</string>
-    <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"允许应用程序随时更改鼠标或触控板指针速度。普通应用程序绝不需要此权限。"</string>
-    <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"向应用程序发送 Linux 信号"</string>
-    <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"允许应用程序请求将提供的信号发送给所有持续的进程。"</string>
-    <string name="permlab_persistentActivity" msgid="8841113627955563938">"让应用程序始终运行"</string>
-    <string name="permdesc_persistentActivity" msgid="4909910271316074418">"允许应用程序持续保留其自身的某些组件,这样系统就无法将其用于其他应用程序。"</string>
-    <string name="permlab_deletePackages" msgid="184385129537705938">"删除应用程序"</string>
-    <string name="permdesc_deletePackages" msgid="7411480275167205081">"允许应用程序删除 Android 程序包。恶意应用程序可能借此删除重要的应用程序。"</string>
-    <string name="permlab_clearAppUserData" msgid="274109191845842756">"删除其他应用程序的数据"</string>
-    <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"允许应用程序清除用户数据。"</string>
-    <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"删除其他应用程序的缓存"</string>
-    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"允许应用程序删除缓存文件。"</string>
-    <string name="permlab_getPackageSize" msgid="7472921768357981986">"计算应用程序存储空间"</string>
-    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"允许应用程序检索其代码、数据和缓存大小"</string>
-    <string name="permlab_installPackages" msgid="2199128482820306924">"直接安装应用程序"</string>
-    <string name="permdesc_installPackages" msgid="5628530972548071284">"允许应用程序安装新的或更新的 Andr​​oid 程序包。恶意应用程序可能借此添加具有任意权限的新应用程序。"</string>
-    <string name="permlab_clearAppCache" msgid="7487279391723526815">"删除所有应用程序缓存数据"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"允许应用程序删除应用程序缓存目录中的文件,从而释放平板电脑的存储空间。对系统进程的访问权限通常受到很大的限制。"</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"允许应用程序删除应用程序缓存目录中的文件,从而释放手机的存储空间。对系统进程的访问权限通常受到很大的限制。"</string>
-    <string name="permlab_movePackage" msgid="3289890271645921411">"移动应用程序资源"</string>
-    <string name="permdesc_movePackage" msgid="319562217778244524">"允许应用程序在内部与外部媒体之间移动应用程序资源。"</string>
+    <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"允许应用随时更改鼠标或触控板指针速度。普通应用绝不需要此权限。"</string>
+    <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"向应用发送 Linux 信号"</string>
+    <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"允许应用请求将提供的信号发送给所有持续的进程。"</string>
+    <string name="permlab_persistentActivity" msgid="8841113627955563938">"让应用始终运行"</string>
+    <string name="permdesc_persistentActivity" msgid="4909910271316074418">"允许应用持续保留其自身的某些组件,这样系统就无法将其用于其他应用。"</string>
+    <string name="permlab_deletePackages" msgid="184385129537705938">"删除应用"</string>
+    <string name="permdesc_deletePackages" msgid="7411480275167205081">"允许应用删除 Android 程序包。恶意应用可能借此删除重要的应用。"</string>
+    <string name="permlab_clearAppUserData" msgid="274109191845842756">"删除其他应用的数据"</string>
+    <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"允许应用清除用户数据。"</string>
+    <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"删除其他应用的缓存"</string>
+    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"允许应用删除缓存文件。"</string>
+    <string name="permlab_getPackageSize" msgid="7472921768357981986">"计算应用存储空间"</string>
+    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"允许应用检索其代码、数据和缓存大小"</string>
+    <string name="permlab_installPackages" msgid="2199128482820306924">"直接安装应用"</string>
+    <string name="permdesc_installPackages" msgid="5628530972548071284">"允许应用安装新的或更新的 Andr​​oid 程序包。恶意应用可能借此添加具有任意权限的新应用。"</string>
+    <string name="permlab_clearAppCache" msgid="7487279391723526815">"删除所有应用缓存数据"</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"允许应用删除应用缓存目录中的文件,从而释放平板电脑的存储空间。对系统进程的访问权限通常受到很大的限制。"</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"允许应用删除应用缓存目录中的文件,从而释放手机的存储空间。对系统进程的访问权限通常受到很大的限制。"</string>
+    <string name="permlab_movePackage" msgid="3289890271645921411">"移动应用资源"</string>
+    <string name="permdesc_movePackage" msgid="319562217778244524">"允许应用在内部与外部媒体之间移动应用资源。"</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"查阅敏感日志数据"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"允许应用程序从系统的各种日志文件中读取信息。这样,应用程序就可以发现关于您平板电脑使用情况的一般信息,其中可能包含个人信息或隐私信息。"</string>
-    <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"允许应用程序从系统的各个日志文件中读取信息。这样,应用程序就可以发现关于您手机使用情况的一般信息,其中可能包含个人信息或隐私信息。"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"允许应用从系统的各种日志文件中读取信息。这样,应用就可以发现关于您平板电脑使用情况的一般信息,其中可能包含个人信息或隐私信息。"</string>
+    <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"允许应用从系统的各个日志文件中读取信息。这样,应用就可以发现关于您手机使用情况的一般信息,其中可能包含个人信息或隐私信息。"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"使用任何媒体解码器进行播放"</string>
-    <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"允许该应用程序使用任何已安装的媒体解码器进行解码,以便播放媒体。"</string>
+    <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"允许该应用使用任何已安装的媒体解码器进行解码,以便播放媒体。"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"读取/写入诊断所拥有的资源"</string>
-    <string name="permdesc_diagnostic" msgid="6608295692002452283">"允许应用程序读取/写入诊断组拥有的所有资源(例如 /dev 中的文件)。这可能会影响系统的稳定性和安全性。此权限仅供制造商或运营商诊断硬件方面的问题时使用。"</string>
-    <string name="permlab_changeComponentState" msgid="6335576775711095931">"启用或停用应用程序组件"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"允许应用程序启用或停用其他应用程序的组件。恶意应用程序可能借此停用重要的平板电脑功能。请务必谨慎使用此权限,因为这可能导致某些应用程序组件处于无法使用、不一致或不稳定的状态。"</string>
-    <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"允许应用程序启用或停用其他应用程序的组件。恶意应用程序可能借此停用重要的手机功能。请务必谨慎使用此权限,因为这可能导致某些应用程序组件进入无法使用、不一致或不稳定的状态。"</string>
+    <string name="permdesc_diagnostic" msgid="6608295692002452283">"允许应用读取/写入诊断组拥有的所有资源(例如 /dev 中的文件)。这可能会影响系统的稳定性和安全性。此权限仅供制造商或运营商诊断硬件方面的问题时使用。"</string>
+    <string name="permlab_changeComponentState" msgid="6335576775711095931">"启用或停用应用组件"</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"允许应用启用或停用其他应用的组件。恶意应用可能借此停用重要的平板电脑功能。请务必谨慎使用此权限,因为这可能导致某些应用组件处于无法使用、不一致或不稳定的状态。"</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"允许应用启用或停用其他应用的组件。恶意应用可能借此停用重要的手机功能。请务必谨慎使用此权限,因为这可能导致某些应用组件进入无法使用、不一致或不稳定的状态。"</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"授予或撤消权限"</string>
     <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"允许应用针对自身或其他应用授予或撤消特定权限。恶意应用可能会借此访问您未授权它们访问的功能。"</string>
-    <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"设置首选应用程序"</string>
-    <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"允许应用程序修改您的首选应用程序。恶意应用程序可能会在后台更改运行的应用程序,欺骗您现有的应用程序,以收集您的私人数据。"</string>
+    <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"设置首选应用"</string>
+    <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"允许应用修改您的首选应用。恶意应用可能会在后台更改运行的应用,欺骗您现有的应用,以收集您的私人数据。"</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"修改全局系统设置"</string>
-    <string name="permdesc_writeSettings" msgid="7775723441558907181">"允许应用程序修改系统的设置数据。恶意应用程序可能会破坏您的系统配置。"</string>
+    <string name="permdesc_writeSettings" msgid="7775723441558907181">"允许应用修改系统的设置数据。恶意应用可能会破坏您的系统配置。"</string>
     <string name="permlab_writeSecureSettings" msgid="204676251876718288">"修改安全系统设置"</string>
-    <string name="permdesc_writeSecureSettings" msgid="8159535613020137391">"允许应用程序修改系统的安全设置数据。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_writeSecureSettings" msgid="8159535613020137391">"允许应用修改系统的安全设置数据。普通应用不能使用此权限。"</string>
     <string name="permlab_writeGservices" msgid="2149426664226152185">"修改 Google 服务地图"</string>
-    <string name="permdesc_writeGservices" msgid="1287309437638380229">"允许应用程序修改 Google 服务地图。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_writeGservices" msgid="1287309437638380229">"允许应用修改 Google 服务地图。普通应用不能使用此权限。"</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"开机时自动启动"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"允许应用程序在系统完成引导后立即自动启动。这样可能会延长平板电脑的启动时间,并允许应用程序始终运行,从而导致平板电脑总体运行速度减慢。"</string>
-    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"允许应用程序在系统完成引导后立即自动启动。这样可能会延长手机的启动时间,并允许应用程序始终运行,从而导致手机总体运行速度减慢。"</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"允许应用在系统完成引导后立即自动启动。这样可能会延长平板电脑的启动时间,并允许应用始终运行,从而导致平板电脑总体运行速度减慢。"</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"允许应用在系统完成引导后立即自动启动。这样可能会延长手机的启动时间,并允许应用始终运行,从而导致手机总体运行速度减慢。"</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"发送持久广播"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"允许应用程序发送持久广播,此类广播在结束后仍会保留。恶意应用程序可能会导致平板电脑使用过多内存,从而使速度变慢或变得不稳定。"</string>
-    <string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"允许应用程序发送持久广播,此类广播在结束后仍会保留。恶意应用程序可能会导致手机使用过多内存,从而使速度变慢或变得不稳定。"</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="1181582512022829259">"允许应用发送持久广播,此类广播在结束后仍会保留。恶意应用可能会导致平板电脑使用过多内存,从而使速度变慢或变得不稳定。"</string>
+    <string name="permdesc_broadcastSticky" product="default" msgid="3287869131621514325">"允许应用发送持久广播,此类广播在结束后仍会保留。恶意应用可能会导致手机使用过多内存,从而使速度变慢或变得不稳定。"</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"读取联系人数据"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="4028657556924039119">"允许应用程序读取您平板电脑上存储的所有联系人(地址)数据。恶意应用程序可能借此将您的数据发送给其他人。"</string>
-    <string name="permdesc_readContacts" product="default" msgid="2032222056456498547">"允许应用程序读取您手机上存储的所有联系人(地址)数据。恶意应用程序可能借此将您的数据发送给其他人。"</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="4028657556924039119">"允许应用读取您平板电脑上存储的所有联系人(地址)数据。恶意应用可能借此将您的数据发送给其他人。"</string>
+    <string name="permdesc_readContacts" product="default" msgid="2032222056456498547">"允许应用读取您手机上存储的所有联系人(地址)数据。恶意应用可能借此将您的数据发送给其他人。"</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"写入联系数据"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="988969759110632978">"允许应用程序读取您平板电脑上存储的联系人(地址)数据。恶意应用程序可能借此清除或修改您的联系人数据。"</string>
-    <string name="permdesc_writeContacts" product="default" msgid="5075164818647934067">"允许应用程序修改您手机上存储的联系人(地址)数据。恶意应用程序可能借此清除或修改您的联系人数据。"</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="988969759110632978">"允许应用读取您平板电脑上存储的联系人(地址)数据。恶意应用可能借此清除或修改您的联系人数据。"</string>
+    <string name="permdesc_writeContacts" product="default" msgid="5075164818647934067">"允许应用修改您手机上存储的联系人(地址)数据。恶意应用可能借此清除或修改您的联系人数据。"</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"读取通话记录"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3995157599976515002">"允许该应用读取平板电脑的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此将您的数据发送给他人。"</string>
     <string name="permdesc_readCallLog" product="default" msgid="3452017559804750758">"允许该应用读取手机的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此将您的数据发送给他人。"</string>
@@ -342,189 +342,189 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"允许该应用修改平板电脑的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此清除或修改您的通话记录。"</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"允许该应用修改手机的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此清除或修改您的通话记录。"</string>
     <string name="permlab_readProfile" msgid="6824681438529842282">"读取您的个人资料数据"</string>
-    <string name="permdesc_readProfile" product="default" msgid="94520753797630679">"允许应用程序读取您设备上存储的个人资料信息,例如您的姓名和联系信息。这意味着应用程序可以识别您的身份,并将您的个人资料信息发送给他人。"</string>
+    <string name="permdesc_readProfile" product="default" msgid="94520753797630679">"允许应用读取您设备上存储的个人资料信息,例如您的姓名和联系信息。这意味着应用可以识别您的身份,并将您的个人资料信息发送给他人。"</string>
     <string name="permlab_writeProfile" msgid="4679878325177177400">"写入到您的个人资料数据"</string>
-    <string name="permdesc_writeProfile" product="default" msgid="4637366723793045603">"允许应用程序更改或添加您设备上存储的个人资料信息,例如您的姓名和联系信息。这意味着其他应用程序可以识别您的身份,并将您的个人资料信息发送给他人。"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="4637366723793045603">"允许应用更改或添加您设备上存储的个人资料信息,例如您的姓名和联系信息。这意味着其他应用可以识别您的身份,并将您的个人资料信息发送给他人。"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"读取您的社交视频流"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="3419050808547335320">"允许应用程序访问并同步您和好友的社交最新动态。恶意应用程序可能借此读取您与社交网络上的好友之间的私人交流信息。"</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="3419050808547335320">"允许应用访问并同步您和好友的社交最新动态。恶意应用可能借此读取您与社交网络上的好友之间的私人交流信息。"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"写入您的社交视频流"</string>
-    <string name="permdesc_writeSocialStream" product="default" msgid="3496277176955721451">"允许应用程序显示好友的社交最新动态。恶意应用程序可能借此冒充您的某位好友,诱骗您泄露密码或其他机密信息。"</string>
+    <string name="permdesc_writeSocialStream" product="default" msgid="3496277176955721451">"允许应用显示好友的社交最新动态。恶意应用可能借此冒充您的某位好友,诱骗您泄露密码或其他机密信息。"</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"读取日历活动和机密信息"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="2338414551004122687">"允许应用程序读取您平板电脑上存储的所有日历活动,包括朋友或同事的活动。恶意应用程序可能会在所有者不知情的情况下,从这些日历活动中提取个人信息。"</string>
-    <string name="permdesc_readCalendar" product="default" msgid="5693933067751827753">"允许应用程序读取您手机上存储的所有日历活动,包括朋友或同事的活动。恶意应用程序可能会在所有者不知情的情况下,从这些日历活动中提取个人信息。"</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="2338414551004122687">"允许应用读取您平板电脑上存储的所有日历活动,包括朋友或同事的活动。恶意应用可能会在所有者不知情的情况下,从这些日历活动中提取个人信息。"</string>
+    <string name="permdesc_readCalendar" product="default" msgid="5693933067751827753">"允许应用读取您手机上存储的所有日历活动,包括朋友或同事的活动。恶意应用可能会在所有者不知情的情况下,从这些日历活动中提取个人信息。"</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"添加或修改日历活动,并在所有者不知情的情况下向邀请对象发送电子邮件"</string>
-    <string name="permdesc_writeCalendar" msgid="2243771395254848873">"允许应用程序以日历所有者的身份发送活动邀请,并添加、删除和更改您可在自己设备上修改的活动,包括朋友或同事的活动。恶意应用程序可能会冒充日历所有者发送垃圾邮件,在所有者不知情的情况下修改活动,或者添加虚假活动。"</string>
+    <string name="permdesc_writeCalendar" msgid="2243771395254848873">"允许应用以日历所有者的身份发送活动邀请,并添加、删除和更改您可在自己设备上修改的活动,包括朋友或同事的活动。恶意应用可能会冒充日历所有者发送垃圾邮件,在所有者不知情的情况下修改活动,或者添加虚假活动。"</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"使用模拟地点来源进行测试"</string>
-    <string name="permdesc_accessMockLocation" msgid="7577931556422993949">"允许应用程序创建模拟位置源以进行测试。恶意应用程序可能借此覆盖由真实位置源(如 GPS 或网络服务提供商)返回的位置和/或状态信息。"</string>
+    <string name="permdesc_accessMockLocation" msgid="7577931556422993949">"允许应用创建模拟位置源以进行测试。恶意应用可能借此覆盖由真实位置源(如 GPS 或网络服务提供商)返回的位置和/或状态信息。"</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"获取额外的位置信息提供程序命令"</string>
-    <string name="permdesc_accessLocationExtraCommands" msgid="6737736970602176133">"允许应用程序访问额外的位置提供程序命令。恶意应用程序可能借此干扰 GPS 或其他位置源的运行。"</string>
+    <string name="permdesc_accessLocationExtraCommands" msgid="6737736970602176133">"允许应用访问额外的位置提供程序命令。恶意应用可能借此干扰 GPS 或其他位置源的运行。"</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"允许安装位置信息提供程序"</string>
-    <string name="permdesc_installLocationProvider" msgid="1742577679350078373">"创建模拟位置源以进行测试。恶意应用程序可能借此覆盖由真实位置源(如 GPS 或网络服务提供商)返回的位置和/或状态信息,或者监视您的位置并将信息提供给外部源。"</string>
+    <string name="permdesc_installLocationProvider" msgid="1742577679350078373">"创建模拟位置源以进行测试。恶意应用可能借此覆盖由真实位置源(如 GPS 或网络服务提供商)返回的位置和/或状态信息,或者监视您的位置并将信息提供给外部源。"</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"精准的(GPS)位置"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="5326423948268164934">"访问精准的位置源,例如平板电脑上的全球定位系统(如果有)。恶意应用程序可能借此确定您所处的位置,并可能消耗额外的电池电量。"</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="7130267914433890869">"访问手机上的精准位置源,例如全球定位系统(如果有)。恶意应用程序可能借此确定您所处的位置,并可能消耗额外的电池电量。"</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="5326423948268164934">"访问精准的位置源,例如平板电脑上的全球定位系统(如果有)。恶意应用可能借此确定您所处的位置,并可能消耗额外的电池电量。"</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="7130267914433890869">"访问手机上的精准位置源,例如全球定位系统(如果有)。恶意应用可能借此确定您所处的位置,并可能消耗额外的电池电量。"</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"(基于网络的)粗略位置"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="5460726396318105483">"访问粗略的位置源(例如蜂窝网络数据库)以确定平板电脑的大体位置(如果可以)。恶意应用程序可能借此确定您所处的大体位置。"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="8900795778057579522">"访问粗略的位置源(例如蜂窝网络数据库)以确定手机的大体位置(如果可以)。恶意应用程序可能借此确定您所处的大体位置。"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="5460726396318105483">"访问粗略的位置源(例如蜂窝网络数据库)以确定平板电脑的大体位置(如果可以)。恶意应用可能借此确定您所处的大体位置。"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="8900795778057579522">"访问粗略的位置源(例如蜂窝网络数据库)以确定手机的大体位置(如果可以)。恶意应用可能借此确定您所处的大体位置。"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"访问 SurfaceFlinger"</string>
-    <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"允许应用程序使用 SurfaceFlinger 低级功能。"</string>
+    <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"允许应用使用 SurfaceFlinger 低级功能。"</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"读取帧缓冲区"</string>
-    <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"允许应用程序读取帧缓冲区的内容。"</string>
+    <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"允许应用读取帧缓冲区的内容。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改您的音频设置"</string>
-    <string name="permdesc_modifyAudioSettings" msgid="7343951185408396919">"允许应用程序修改全局音频设置,如音量和路由。"</string>
+    <string name="permdesc_modifyAudioSettings" msgid="7343951185408396919">"允许应用修改全局音频设置,如音量和路由。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"录音"</string>
-    <string name="permdesc_recordAudio" msgid="2387462233976248635">"允许应用程序访问录音路径。"</string>
+    <string name="permdesc_recordAudio" msgid="2387462233976248635">"允许应用访问录音路径。"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"拍摄照片和视频"</string>
-    <string name="permdesc_camera" msgid="1507407407002492176">"允许应用程序使用相机拍摄照片和视频。该权限可让应用程序随时收集相机的取景。"</string>
+    <string name="permdesc_camera" msgid="1507407407002492176">"允许应用使用相机拍摄照片和视频。该权限可让应用随时收集相机的取景。"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"永久停用平板电脑"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"永久停用手机"</string>
-    <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"允许应用程序永久停用整个平板电脑,但这样非常危险。"</string>
-    <string name="permdesc_brick" product="default" msgid="5788903297627283099">"允许应用程序永久停用整个手机,但这非常危险。"</string>
+    <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"允许应用永久停用整个平板电脑,但这样非常危险。"</string>
+    <string name="permdesc_brick" product="default" msgid="5788903297627283099">"允许应用永久停用整个手机,但这非常危险。"</string>
     <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"强行重新启动平板电脑"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"强行重新启动手机"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"允许应用程序强行重新启动平板电脑。"</string>
-    <string name="permdesc_reboot" product="default" msgid="5326008124289989969">"允许应用程序强行重新启动手机。"</string>
+    <string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"允许应用强行重新启动平板电脑。"</string>
+    <string name="permdesc_reboot" product="default" msgid="5326008124289989969">"允许应用强行重新启动手机。"</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"装载和卸载文件系统"</string>
-    <string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"允许应用程序装载和卸载可移动存储设备的文件系统。"</string>
+    <string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"允许应用装载和卸载可移动存储设备的文件系统。"</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"格式化外部存储设备"</string>
-    <string name="permdesc_mount_format_filesystems" msgid="8784268246779198627">"允许应用程序格式化可移动存储设备。"</string>
+    <string name="permdesc_mount_format_filesystems" msgid="8784268246779198627">"允许应用格式化可移动存储设备。"</string>
     <string name="permlab_asec_access" msgid="3411338632002193846">"获取有关内部存储设备的信息"</string>
-    <string name="permdesc_asec_access" msgid="3094563844593878548">"允许应用程序获取有关内存设备的信息。"</string>
+    <string name="permdesc_asec_access" msgid="3094563844593878548">"允许应用获取有关内存设备的信息。"</string>
     <string name="permlab_asec_create" msgid="6414757234789336327">"创建内部存储设备"</string>
-    <string name="permdesc_asec_create" msgid="4558869273585856876">"允许应用程序创建内存设备。"</string>
+    <string name="permdesc_asec_create" msgid="4558869273585856876">"允许应用创建内存设备。"</string>
     <string name="permlab_asec_destroy" msgid="526928328301618022">"清除内部存储设备"</string>
-    <string name="permdesc_asec_destroy" msgid="7218749286145526537">"允许应用程序清除内存设备。"</string>
+    <string name="permdesc_asec_destroy" msgid="7218749286145526537">"允许应用清除内存设备。"</string>
     <string name="permlab_asec_mount_unmount" msgid="8877998101944999386">"装载/卸载内存设备"</string>
-    <string name="permdesc_asec_mount_unmount" msgid="3451360114902490929">"允许应用程序装载/卸载内存设备。"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="3451360114902490929">"允许应用装载/卸载内存设备。"</string>
     <string name="permlab_asec_rename" msgid="7496633954080472417">"重命名内部存储设备"</string>
-    <string name="permdesc_asec_rename" msgid="1794757588472127675">"允许应用程序重命名内存设备。"</string>
+    <string name="permdesc_asec_rename" msgid="1794757588472127675">"允许应用重命名内存设备。"</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"控制振动器"</string>
-    <string name="permdesc_vibrate" msgid="6284989245902300945">"允许应用程序控制振动器。"</string>
+    <string name="permdesc_vibrate" msgid="6284989245902300945">"允许应用控制振动器。"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"控制闪光灯"</string>
-    <string name="permdesc_flashlight" msgid="6522284794568368310">"允许应用程序控制闪光灯。"</string>
+    <string name="permdesc_flashlight" msgid="6522284794568368310">"允许应用控制闪光灯。"</string>
     <string name="permlab_manageUsb" msgid="1113453430645402723">"管理 USB 设备的偏好设置和权限"</string>
-    <string name="permdesc_manageUsb" msgid="7776155430218239833">"允许应用程序管理针对 USB 设备的偏好设置和权限。"</string>
+    <string name="permdesc_manageUsb" msgid="7776155430218239833">"允许应用管理针对 USB 设备的偏好设置和权限。"</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"应用 MTP 协议"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"允许访问内核 MTP 驱动程序,以便应用 MTP USB 协议。"</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"测试硬件"</string>
-    <string name="permdesc_hardware_test" msgid="6597964191208016605">"允许应用程序控制各种外围设备以进行硬件测试。"</string>
+    <string name="permdesc_hardware_test" msgid="6597964191208016605">"允许应用控制各种外围设备以进行硬件测试。"</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"直接拨打电话号码"</string>
-    <string name="permdesc_callPhone" msgid="6396463004110544744">"允许应用程序在没有您干预的情况下呼叫电话号码。恶意应用程序可能会产生意料之外的话费。请注意,此权限不允许应用程序呼叫紧急电话。"</string>
+    <string name="permdesc_callPhone" msgid="6396463004110544744">"允许应用在没有您干预的情况下呼叫电话号码。恶意应用可能会产生意料之外的话费。请注意,此权限不允许应用呼叫紧急电话。"</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"直接呼叫任何电话号码"</string>
-    <string name="permdesc_callPrivileged" msgid="1689024901509996810">"允许应用程序在没有您干预的情况下呼叫任何电话号码,包括紧急呼叫号码。恶意应用程序可能会向紧急服务进行多余以及非法呼叫。"</string>
+    <string name="permdesc_callPrivileged" msgid="1689024901509996810">"允许应用在没有您干预的情况下呼叫任何电话号码,包括紧急呼叫号码。恶意应用可能会向紧急服务进行多余以及非法呼叫。"</string>
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"直接启动 CDMA 平板电脑设置"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"直接启动 CDMA 电话设置"</string>
-    <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"允许应用程序启动 CDMA 配置。恶意应用程序可能会无端启动 CDMA 配置。"</string>
+    <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"允许应用启动 CDMA 配置。恶意应用可能会无端启动 CDMA 配置。"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"控制位置更新通知"</string>
-    <string name="permdesc_locationUpdates" msgid="1120741557891438876">"允许应用程序启用/停用来自无线装置的位置更新通知。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_locationUpdates" msgid="1120741557891438876">"允许应用启用/停用来自无线装置的位置更新通知。普通应用不能使用此权限。"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"访问检入属性"</string>
-    <string name="permdesc_checkinProperties" msgid="4024526968630194128">"允许应用程序对登记服务上传的属性拥有读取/写入权限。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_checkinProperties" msgid="4024526968630194128">"允许应用对登记服务上传的属性拥有读取/写入权限。普通应用不能使用此权限。"</string>
     <string name="permlab_bindGadget" msgid="776905339015863471">"选择窗口小部件"</string>
-    <string name="permdesc_bindGadget" msgid="8261326938599049290">"允许应用程序告知系统哪些窗口小部件可供哪个应用程序使用。拥有此权限的应用程序可向其他应用程序授予对个人资料的访问权限。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_bindGadget" msgid="8261326938599049290">"允许应用告知系统哪些窗口小部件可供哪个应用使用。拥有此权限的应用可向其他应用授予对个人资料的访问权限。普通应用不能使用此权限。"</string>
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"修改手机状态"</string>
-    <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"允许应用程序控制设备的电话功能。拥有此权限的应用程序可在不通知您的情况下执行切换网络、开关手机无线装置等此类操作。"</string>
+    <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"允许应用控制设备的电话功能。拥有此权限的应用可在不通知您的情况下执行切换网络、开关手机无线装置等此类操作。"</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"读取手机状态和身份"</string>
-    <string name="permdesc_readPhoneState" msgid="5127767618743602782">"允许应用程序访问设备的电话功能。拥有此权限的应用程序可以确定本机的电话号码和序列号、通话是否有效、呼叫的号码等。"</string>
+    <string name="permdesc_readPhoneState" msgid="5127767618743602782">"允许应用访问设备的电话功能。拥有此权限的应用可以确定本机的电话号码和序列号、通话是否有效、呼叫的号码等。"</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"阻止平板电脑进入休眠状态"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手机休眠"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"允许应用程序阻止平板电脑进入休眠状态。"</string>
-    <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"允许应用程序阻止手机进入休眠状态。"</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"允许应用阻止平板电脑进入休眠状态。"</string>
+    <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"允许应用阻止手机进入休眠状态。"</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"打开或关闭平板电脑"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"开机或关机"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="6689862878984631831">"允许应用程序打开或关闭平板电脑。"</string>
-    <string name="permdesc_devicePower" product="default" msgid="6037057348463131032">"允许应用程序打开或关闭手机。"</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="6689862878984631831">"允许应用打开或关闭平板电脑。"</string>
+    <string name="permdesc_devicePower" product="default" msgid="6037057348463131032">"允许应用打开或关闭手机。"</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"在出厂测试模式下运行"</string>
     <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"作为低级制造商测试运行,从而允许对平板电脑硬件进行完全访问。此权限仅当平板电脑在制造商测试模式下运行时才可用。"</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"作为一项低级制造商测试来运行,从而允许对手机硬件进行完全访问。此权限仅当手机在制造商测试模式下运行时才可用。。"</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"设置壁纸"</string>
-    <string name="permdesc_setWallpaper" msgid="7373447920977624745">"允许应用程序设置系统壁纸。"</string>
+    <string name="permdesc_setWallpaper" msgid="7373447920977624745">"允许应用设置系统壁纸。"</string>
     <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"设置有关壁纸大小的提示"</string>
-    <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"允许应用程序设置有关系统壁纸大小的提示。"</string>
+    <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"允许应用设置有关系统壁纸大小的提示。"</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"将系统恢复为出厂设置"</string>
-    <string name="permdesc_masterClear" msgid="3665380492633910226">"允许应用程序将系统完全重置为其出厂设置,这会清除所有数据、配置和已安装的应用程序。"</string>
+    <string name="permdesc_masterClear" msgid="3665380492633910226">"允许应用将系统完全重置为其出厂设置,这会清除所有数据、配置和已安装的应用。"</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"设置时间"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"允许应用程序更改平板电脑的时间。"</string>
-    <string name="permdesc_setTime" product="default" msgid="1855702730738020">"允许应用程序更改手机的时间。"</string>
+    <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"允许应用更改平板电脑的时间。"</string>
+    <string name="permdesc_setTime" product="default" msgid="1855702730738020">"允许应用更改手机的时间。"</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"设置时区"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"允许应用程序更改平板电脑的时区。"</string>
-    <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"允许应用程序更改手机的时区。"</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"允许应用更改平板电脑的时区。"</string>
+    <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"允许应用更改手机的时区。"</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"作为 AccountManagerService"</string>
-    <string name="permdesc_accountManagerService" msgid="1948455552333615954">"允许该应用程序调用 AccountAuthenticators。"</string>
+    <string name="permdesc_accountManagerService" msgid="1948455552333615954">"允许该应用调用 AccountAuthenticators。"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"发现已知帐户"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="3238360555257773358">"允许应用程序获取平板电脑已知的帐户列表。"</string>
-    <string name="permdesc_getAccounts" product="default" msgid="2735689364629830348">"允许应用程序获取手机已知的帐户列表。"</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="3238360555257773358">"允许应用获取平板电脑已知的帐户列表。"</string>
+    <string name="permdesc_getAccounts" product="default" msgid="2735689364629830348">"允许应用获取手机已知的帐户列表。"</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"作为帐户身份验证程序"</string>
-    <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"允许应用程序使用 AccountManager 的帐户身份验证程序功能,包括创建帐户以及获取和设置其密码。"</string>
+    <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"允许应用使用 AccountManager 的帐户身份验证程序功能,包括创建帐户以及获取和设置其密码。"</string>
     <string name="permlab_manageAccounts" msgid="4440380488312204365">"管理帐户列表"</string>
-    <string name="permdesc_manageAccounts" msgid="8698295625488292506">"允许应用程序执行添加帐户、删除帐户、删除帐户密码等操作。"</string>
+    <string name="permdesc_manageAccounts" msgid="8698295625488292506">"允许应用执行添加帐户、删除帐户、删除帐户密码等操作。"</string>
     <string name="permlab_useCredentials" msgid="6401886092818819856">"使用帐户的身份验证凭据"</string>
-    <string name="permdesc_useCredentials" msgid="7984227147403346422">"允许应用程序请求身份验证令牌。"</string>
+    <string name="permdesc_useCredentials" msgid="7984227147403346422">"允许应用请求身份验证令牌。"</string>
     <string name="permlab_accessNetworkState" msgid="6865575199464405769">"查看网络状态"</string>
-    <string name="permdesc_accessNetworkState" msgid="479772796952547198">"允许应用程序查看所有网络的状态。"</string>
+    <string name="permdesc_accessNetworkState" msgid="479772796952547198">"允许应用查看所有网络的状态。"</string>
     <string name="permlab_createNetworkSockets" msgid="9121633680349549585">"完全的互联网访问权限"</string>
-    <string name="permdesc_createNetworkSockets" msgid="5963922297444265950">"允许应用程序创建网络套接字。"</string>
+    <string name="permdesc_createNetworkSockets" msgid="5963922297444265950">"允许应用创建网络套接字。"</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"更改/拦截网络设置和流量"</string>
-    <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"允许应用程序更改网络设置,并拦截和检查所有网络流量,例如更改任意 APN 的代理和端口。恶意应用程序可能会在您不知情的情况下监视、重定向或修改网络数据包。"</string>
+    <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"允许应用更改网络设置,并拦截和检查所有网络流量,例如更改任意 APN 的代理和端口。恶意应用可能会在您不知情的情况下监视、重定向或修改网络数据包。"</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"更改网络连接性"</string>
-    <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"允许应用程序更改网络连接的状态。"</string>
+    <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"允许应用更改网络连接的状态。"</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"更改网络共享连接"</string>
-    <string name="permdesc_changeTetherState" msgid="1524441344412319780">"允许应用程序更改绑定网络连接的状态。"</string>
+    <string name="permdesc_changeTetherState" msgid="1524441344412319780">"允许应用更改绑定网络连接的状态。"</string>
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"更改后台数据使用设置"</string>
-    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"允许应用程序更改后台数据使用设置。"</string>
+    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"允许应用更改后台数据使用设置。"</string>
     <string name="permlab_accessWifiState" msgid="8100926650211034400">"查看 Wi-Fi 状态"</string>
-    <string name="permdesc_accessWifiState" msgid="7770452658226256831">"允许应用程序查看有关 Wi-Fi 状态的信息。"</string>
+    <string name="permdesc_accessWifiState" msgid="7770452658226256831">"允许应用查看有关 Wi-Fi 状态的信息。"</string>
     <string name="permlab_changeWifiState" msgid="7280632711057112137">"更改 Wi-Fi 状态"</string>
-    <string name="permdesc_changeWifiState" msgid="7399961004537946240">"允许应用程序与 Wi-Fi 接入点建立和断开连接,并对配置的 Wi-Fi 网络进行更改。"</string>
+    <string name="permdesc_changeWifiState" msgid="7399961004537946240">"允许应用与 Wi-Fi 接入点建立和断开连接,并对配置的 Wi-Fi 网络进行更改。"</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"允许接收 Wi-Fi 多播"</string>
-    <string name="permdesc_changeWifiMulticastState" msgid="7633598524564320817">"允许应用程序接收并非直接发送至您设备的数据包。在查找附近提供的服务时,此权限很有用。这种操作所耗电量大于非多播模式。"</string>
+    <string name="permdesc_changeWifiMulticastState" msgid="7633598524564320817">"允许应用接收并非直接发送至您设备的数据包。在查找附近提供的服务时,此权限很有用。这种操作所耗电量大于非多播模式。"</string>
     <string name="permlab_bluetoothAdmin" msgid="3606576270792236062">"蓝牙管理"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"允许应用程序配置本地蓝牙平板电脑,以及发现远程设备并进行配对。"</string>
-    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"允许应用程序配置本地蓝牙手机,以及发现远程设备并进行配对。"</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"允许应用配置本地蓝牙平板电脑,以及发现远程设备并进行配对。"</string>
+    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"允许应用配置本地蓝牙手机,以及发现远程设备并进行配对。"</string>
     <string name="permlab_accessWimaxState" msgid="1232061307208861588">"查看 WiMAX 状态"</string>
-    <string name="permdesc_accessWimaxState" msgid="5914958077555177749">"允许该应用程序查看有关 WiMAX 状态的信息。"</string>
+    <string name="permdesc_accessWimaxState" msgid="5914958077555177749">"允许该应用查看有关 WiMAX 状态的信息。"</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"更改 WiMAX 状态"</string>
-    <string name="permdesc_changeWimaxState" msgid="3328853825006455912">"允许该应用程序连接到 WiMAX 网络以及从 WiMAX 网络断开连接。"</string>
+    <string name="permdesc_changeWimaxState" msgid="3328853825006455912">"允许该应用连接到 WiMAX 网络以及从 WiMAX 网络断开连接。"</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"创建蓝牙连接"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="7007851048416363446">"允许应用程序查看本地蓝牙平板电脑的配置,以及建立和接受与配对设备的连接。"</string>
-    <string name="permdesc_bluetooth" product="default" msgid="31846362767164948">"允许应用程序查看本地蓝牙手机的配置,以及建立和接受与配对设备的连接。"</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="7007851048416363446">"允许应用查看本地蓝牙平板电脑的配置,以及建立和接受与配对设备的连接。"</string>
+    <string name="permdesc_bluetooth" product="default" msgid="31846362767164948">"允许应用查看本地蓝牙手机的配置,以及建立和接受与配对设备的连接。"</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"控制近距离通信"</string>
-    <string name="permdesc_nfc" msgid="7120611819401789907">"允许应用程序与近距离无线通信 (NFC) 标记、卡和阅读器进行通信。"</string>
+    <string name="permdesc_nfc" msgid="7120611819401789907">"允许应用与近距离无线通信 (NFC) 标记、卡和阅读器进行通信。"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用键锁"</string>
-    <string name="permdesc_disableKeyguard" msgid="6231611286892232626">"允许应用程序停用键锁和任何关联的密码安全设置。例如,在手机上接听电话时停用键锁,在通话结束后重新启用键锁。"</string>
+    <string name="permdesc_disableKeyguard" msgid="6231611286892232626">"允许应用停用键锁和任何关联的密码安全设置。例如,在手机上接听电话时停用键锁,在通话结束后重新启用键锁。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"读取同步设置"</string>
-    <string name="permdesc_readSyncSettings" msgid="5464056785274229278">"允许应用程序读取同步设置,例如是否对“联系人”应用程序启用同步功能。"</string>
+    <string name="permdesc_readSyncSettings" msgid="5464056785274229278">"允许应用读取同步设置,例如是否对“联系人”应用启用同步功能。"</string>
     <string name="permlab_writeSyncSettings" msgid="6297138566442486462">"写入同步设置"</string>
-    <string name="permdesc_writeSyncSettings" msgid="1466056564502117130">"允许应用程序修改同步设置,例如是否对“联系人”应用程序启用同步功能。"</string>
+    <string name="permdesc_writeSyncSettings" msgid="1466056564502117130">"允许应用修改同步设置,例如是否对“联系人”应用启用同步功能。"</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"读取同步统计信息"</string>
-    <string name="permdesc_readSyncStats" msgid="3801971839939951678">"允许应用程序读取同步统计信息;例如,已发生的同步历史记录。"</string>
+    <string name="permdesc_readSyncStats" msgid="3801971839939951678">"允许应用读取同步统计信息;例如,已发生的同步历史记录。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"读取订阅的供稿"</string>
-    <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"允许应用程序获取有关当前同步的 Feed 的详情。"</string>
+    <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"允许应用获取有关当前同步的 Feed 的详情。"</string>
     <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"写入订阅的供稿"</string>
-    <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"允许应用程序修改您当前同步的 Feed。恶意应用程序可能会更改您的同步 Feed。"</string>
+    <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"允许应用修改您当前同步的 Feed。恶意应用可能会更改您的同步 Feed。"</string>
     <string name="permlab_readDictionary" msgid="8410247960433376352">"读取用户定义的词典"</string>
-    <string name="permdesc_readDictionary" msgid="8977815988329283705">"允许应用程序读取用户可能在用户词典中已存储的任意私有字词、名称和短语。"</string>
+    <string name="permdesc_readDictionary" msgid="8977815988329283705">"允许应用读取用户可能在用户词典中已存储的任意私有字词、名称和短语。"</string>
     <string name="permlab_writeDictionary" msgid="2296383164914812772">"写入用户定义的词典"</string>
-    <string name="permdesc_writeDictionary" msgid="8185385716255065291">"允许应用程序向用户词典中写入新词。"</string>
+    <string name="permdesc_writeDictionary" msgid="8185385716255065291">"允许应用向用户词典中写入新词。"</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="4086221374639183281">"读取 USB 存储设备的内容"</string>
     <string name="permlab_sdcardRead" product="default" msgid="8537875151845139539">"读取 SD 卡的内容"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="1055302898999352339">"允许应用读取 USB 存储设备的内容。"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="7947792373570683542">"允许应用读取 SD 卡的内容。"</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"修改/删除 USB 存储设备内容"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"修改/删除 SD 卡中的内容"</string>
-    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"允许应用程序写入 USB 存储设备。"</string>
-    <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"允许应用程序写入 SD 卡。"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"允许应用写入 USB 存储设备。"</string>
+    <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"允许应用写入 SD 卡。"</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"修改/删除内部媒体存储设备的内容"</string>
-    <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"允许应用程序修改内部媒体存储设备的内容。"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"允许应用修改内部媒体存储设备的内容。"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"访问缓存文件系统"</string>
-    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允许应用程序读取和写入缓存文件系统。"</string>
+    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允许应用读取和写入缓存文件系统。"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"拨打/接听互联网通话"</string>
-    <string name="permdesc_use_sip" msgid="4717632000062674294">"允许应用程序使用 SIP 服务拨打/接听互联网电话。"</string>
+    <string name="permdesc_use_sip" msgid="4717632000062674294">"允许应用使用 SIP 服务拨打/接听互联网电话。"</string>
     <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"读取网络使用情况历史记录"</string>
-    <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"允许应用程序读取特定网络和应用程序的网络使用情况历史记录。"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"允许应用读取特定网络和应用的网络使用情况历史记录。"</string>
     <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"管理网络政策"</string>
-    <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"允许应用程序管理网络政策和定义专门针对应用程序的规则。"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"允许应用管理网络政策和定义专门针对应用的规则。"</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"修改网络使用情况记录方式"</string>
-    <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"允许该应用程序修改对于各应用程序的网络使用情况的统计方式。普通应用程序不应使用此权限。"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"允许该应用修改对于各应用的网络使用情况的统计方式。普通应用不应使用此权限。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解锁密码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
@@ -542,7 +542,7 @@
     <string name="policylab_expirePassword" msgid="885279151847254056">"设置锁定屏幕密码的有效期"</string>
     <string name="policydesc_expirePassword" msgid="1729725226314691591">"控制系统强制用户更改屏幕锁定密码的频率。"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"设置存储设备加密"</string>
-    <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"要求对存储的应用程序数据进行加密。"</string>
+    <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"要求对存储的应用数据进行加密。"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"停用相机"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"禁止使用所有设备摄像头。"</string>
   <string-array name="phoneTypes">
@@ -760,20 +760,20 @@
     <string name="autofill_area" msgid="3547409050889952423">"区域"</string>
     <string name="autofill_emirate" msgid="2893880978835698818">"酋长国"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"读取浏览器的历史记录和书签"</string>
-    <string name="permdesc_readHistoryBookmarks" msgid="4577476392604595921">"允许应用程序读取“浏览器”访问过的所有网址,以及“浏览器”的所有书签。"</string>
+    <string name="permdesc_readHistoryBookmarks" msgid="4577476392604595921">"允许应用读取“浏览器”访问过的所有网址,以及“浏览器”的所有书签。"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"写入浏览器的历史记录和书签"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="1757103804824209530">"允许应用程序修改“浏览器”存储在平板电脑上的历史记录或书签。恶意应用程序可能借此删除或修改“浏览器”的数据。"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="6693764355720719197">"允许应用程序修改“浏览器”存储在手机上的历史记录或书签。恶意应用程序可能借此删除或修改“浏览器”的数据。"</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="1757103804824209530">"允许应用修改“浏览器”存储在平板电脑上的历史记录或书签。恶意应用可能借此删除或修改“浏览器”的数据。"</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="6693764355720719197">"允许应用修改“浏览器”存储在手机上的历史记录或书签。恶意应用可能借此删除或修改“浏览器”的数据。"</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"在闹钟中设置警报"</string>
-    <string name="permdesc_setAlarm" msgid="316392039157473848">"允许应用程序在已安装的闹钟应用程序中设置闹钟。有些闹钟应用程序可能无法实现此功能。"</string>
+    <string name="permdesc_setAlarm" msgid="316392039157473848">"允许应用在已安装的闹钟应用中设置闹钟。有些闹钟应用可能无法实现此功能。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"添加语音邮件"</string>
-    <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允许应用程序向您的语音信箱收件箱添加邮件。"</string>
+    <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允许应用向您的语音信箱收件箱添加邮件。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改“浏览器”地理位置的权限"</string>
-    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允许应用程序修改“浏览器”的地理位置权限。恶意应用程序可能借此向任意网站发送位置信息。"</string>
+    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允许应用修改“浏览器”的地理位置权限。恶意应用可能借此向任意网站发送位置信息。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"验证软件包"</string>
-    <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"允许应用程序验证程序包是否可以安装。"</string>
+    <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"允许应用验证程序包是否可以安装。"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"绑定到软件包验证程序"</string>
-    <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"允许用户请求使用程序包验证程序。普通应用程序绝不需要此权限。"</string>
+    <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"允许用户请求使用程序包验证程序。普通应用绝不需要此权限。"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"访问串行端口"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"允许持有人使用 SerialManager API 访问串行端口。"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"从外部访问内容提供程序"</string>
@@ -918,12 +918,12 @@
     <string name="loading" msgid="7933681260296021180">"正在加载..."</string>
     <string name="capital_on" msgid="1544682755514494298">"打开"</string>
     <string name="capital_off" msgid="6815870386972805832">"关闭"</string>
-    <string name="whichApplication" msgid="4533185947064773386">"选择要使用的应用程序:"</string>
+    <string name="whichApplication" msgid="4533185947064773386">"选择要使用的应用:"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"设为默认选项。"</string>
-    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"在“系统设置”&gt;“应用程序”&gt;“已下载”中清除默认设置。"</string>
+    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"在“系统设置”&gt;“应用”&gt;“已下载”中清除默认设置。"</string>
     <string name="chooseActivity" msgid="7486876147751803333">"选择操作"</string>
-    <string name="chooseUsbActivity" msgid="6894748416073583509">"为 USB 设备选择一个应用程序"</string>
-    <string name="noApplications" msgid="2991814273936504689">"没有应用程序可执行此操作。"</string>
+    <string name="chooseUsbActivity" msgid="6894748416073583509">"为 USB 设备选择一个应用"</string>
+    <string name="noApplications" msgid="2991814273936504689">"没有应用可执行此操作。"</string>
     <string name="aerr_title" msgid="1905800560317137752"></string>
     <string name="aerr_application" msgid="932628488013092776">"很抱歉,“<xliff:g id="APPLICATION">%1$s</xliff:g>”已停止运行。"</string>
     <string name="aerr_process" msgid="4507058997035697579">"抱歉,进程“<xliff:g id="PROCESS">%1$s</xliff:g>”已停止运行。"</string>
@@ -936,26 +936,26 @@
     <string name="report" msgid="4060218260984795706">"报告"</string>
     <string name="wait" msgid="7147118217226317732">"等待"</string>
     <string name="webpage_unresponsive" msgid="3272758351138122503">"该网页已无响应。"\n\n"要将其关闭吗?"</string>
-    <string name="launch_warning_title" msgid="1547997780506713581">"应用程序已重定向"</string>
+    <string name="launch_warning_title" msgid="1547997780506713581">"应用已重定向"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g>目前正在运行。"</string>
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g>已启动。"</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"缩放"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"始终显示"</string>
-    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"在“系统设置”&gt;“应用程序”&gt;“已下载”中重新启用此模式。"</string>
-    <string name="smv_application" msgid="3307209192155442829">"“<xliff:g id="APPLICATION">%1$s</xliff:g>”应用程序(<xliff:g id="PROCESS">%2$s</xliff:g> 进程)违反了自我强制执行的严格模式 (StrictMode) 政策。"</string>
+    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"在“系统设置”&gt;“应用”&gt;“已下载”中重新启用此模式。"</string>
+    <string name="smv_application" msgid="3307209192155442829">"“<xliff:g id="APPLICATION">%1$s</xliff:g>”应用(<xliff:g id="PROCESS">%2$s</xliff:g> 进程)违反了自我强制执行的严格模式 (StrictMode) 政策。"</string>
     <string name="smv_process" msgid="5120397012047462446">"进程 <xliff:g id="PROCESS">%1$s</xliff:g> 违反了自我强制执行的严格模式 (StrictMode) 政策。"</string>
     <string name="android_upgrading_title" msgid="1584192285441405746">"Android 正在升级..."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"正在优化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> 个(共 <xliff:g id="NUMBER_1">%2$d</xliff:g> 个)。"</string>
-    <string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在启动应用程序。"</string>
+    <string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在启动应用。"</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"即将完成启动。"</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g>正在运行"</string>
-    <string name="heavy_weight_notification_detail" msgid="1721681741617898865">"触摸可切换至应用程序"</string>
-    <string name="heavy_weight_switcher_title" msgid="7153167085403298169">"切换应用程序吗?"</string>
-    <string name="heavy_weight_switcher_text" msgid="7022631924534406403">"已有一个应用程序正在运行,要启动新的应用程序,您必须先停止该应用程序。"</string>
+    <string name="heavy_weight_notification_detail" msgid="1721681741617898865">"触摸可切换至应用"</string>
+    <string name="heavy_weight_switcher_title" msgid="7153167085403298169">"切换应用吗?"</string>
+    <string name="heavy_weight_switcher_text" msgid="7022631924534406403">"已有一个应用正在运行,要启动新的应用,您必须先停止该应用。"</string>
     <string name="old_app_action" msgid="493129172238566282">"返回至<xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
-    <string name="old_app_description" msgid="2082094275580358049">"不启动新的应用程序。"</string>
+    <string name="old_app_description" msgid="2082094275580358049">"不启动新的应用。"</string>
     <string name="new_app_action" msgid="5472756926945440706">"启动<xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
-    <string name="new_app_description" msgid="1932143598371537340">"停止旧的应用程序,但不保存。"</string>
+    <string name="new_app_description" msgid="1932143598371537340">"停止旧的应用,但不保存。"</string>
     <string name="sendText" msgid="5209874571959469142">"选择要对文字执行的操作"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"铃声音量"</string>
     <string name="volume_music" msgid="5421651157138628171">"媒体音量"</string>
@@ -1003,7 +1003,7 @@
     <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"键入所需的 PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
     <string name="select_character" msgid="3365550120617701745">"插入字符"</string>
-    <string name="sms_control_default_app_name" msgid="3058577482636640465">"未知应用程序"</string>
+    <string name="sms_control_default_app_name" msgid="3058577482636640465">"未知应用"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"正在发送短信"</string>
     <string name="sms_control_message" msgid="4073755190243093924">"正在发送大量短信。触摸“确定”继续,或触摸“取消”停止发送。"</string>
     <string name="sms_control_yes" msgid="2532062172402615953">"确定"</string>
@@ -1039,7 +1039,7 @@
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"关闭 USB 存储设备"</string>
     <string name="usb_storage_stop_error_message" msgid="1970374898263063836">"关闭 USB 存储设备时遇到问题。请检查您是否已卸载了 USB 主设备,然后重试。"</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"打开 USB 存储设备"</string>
-    <string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"如果您打开 USB 存储设备,您正在使用的某些应用程序将会停止,并且在您关闭 USB 存储设备前都将无法使用。"</string>
+    <string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"如果您打开 USB 存储设备,您正在使用的某些应用将会停止,并且在您关闭 USB 存储设备前都将无法使用。"</string>
     <string name="dlg_error_title" msgid="7323658469626514207">"USB 操作失败"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"确定"</string>
     <string name="usb_mtp_notification_title" msgid="3699913097391550394">"作为媒体设备连接"</string>
@@ -1084,9 +1084,9 @@
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD 卡已移除。请插入新的 SD 卡。"</string>
     <string name="activity_list_empty" msgid="1675388330786841066">"未找到匹配的活动。"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"更新组件使用情况统计"</string>
-    <string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"允许应用程序修改收集到的组件使用情况统计信息。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"允许应用修改收集到的组件使用情况统计信息。普通应用不能使用此权限。"</string>
     <string name="permlab_copyProtectedData" msgid="4341036311211406692">"复制内容"</string>
-    <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"允许应用程序调用默认的容器服务,以便复制内容。普通应用程序不能使用此权限。"</string>
+    <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"允许应用调用默认的容器服务,以便复制内容。普通应用不能使用此权限。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"触摸两次可进行缩放控制"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"无法添加窗口小部件。"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"开始"</string>
@@ -1098,13 +1098,13 @@
     <string name="ime_action_default" msgid="2840921885558045721">"执行"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"拨打电话"\n"<xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"创建电话号码为"\n"<xliff:g id="NUMBER">%s</xliff:g> 的联系人"</string>
-    <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"以下一个或多个应用程序请求获得相应权限,以便在当前和以后访问您的帐户。"</string>
+    <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"以下一个或多个应用请求获得相应权限,以便在当前和以后访问您的帐户。"</string>
     <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"您是否同意此请求?"</string>
     <string name="grant_permissions_header_text" msgid="6874497408201826708">"访问权限请求"</string>
     <string name="allow" msgid="7225948811296386551">"允许"</string>
     <string name="deny" msgid="2081879885755434506">"拒绝"</string>
     <string name="permission_request_notification_title" msgid="6486759795926237907">"许可权限请求"</string>
-    <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"应用程序对帐户 <xliff:g id="ACCOUNT">%s</xliff:g>"\n" 提出权限请求。"</string>
+    <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"应用对帐户 <xliff:g id="ACCOUNT">%s</xliff:g>"\n" 提出权限请求。"</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"输入法"</string>
     <string name="sync_binding_label" msgid="3687969138375092423">"同步"</string>
     <string name="accessibility_binding_label" msgid="4148120742096474641">"辅助功能"</string>
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"添加帐户"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"增加"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"减少"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"触摸 <xliff:g id="VALUE">%s</xliff:g> 次并按住。"</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"向上滑动可增加值,向下滑动可减少值。"</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"增加分钟数"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"减少分钟数"</string>
@@ -1196,7 +1197,7 @@
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"模式更改"</string>
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
-    <string name="activitychooserview_choose_application" msgid="2125168057199941199">"选择应用程序"</string>
+    <string name="activitychooserview_choose_application" msgid="2125168057199941199">"选择应用"</string>
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"共享对象"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"与“<xliff:g id="APPLICATION_NAME">%s</xliff:g>”共享"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"滑动手柄。触摸并按住。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index e5a15de..3fc2f34 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1169,6 +1169,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"新增帳戶"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"增加"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"減少"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> 輕觸並按住。"</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"向上滑動即可增加,向下滑動即可減少。"</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"增加分鐘數"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"減少分鐘數"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c50a1a8..f43835f 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1168,6 +1168,7 @@
     <string name="add_account_button_label" msgid="3611982894853435874">"Engeza i-akhawunti"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Nciphisa"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decrement"</string>
+    <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> thinta bese ucindezela."</string>
     <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Shishilizisa kwenyuke kuye ekwenyusweni kwehle kuye ekwehlisweni."</string>
     <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Iminithi wokwenyusa"</string>
     <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Iminithi yokwehlisa"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4d9b043a..4fde018 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -284,6 +284,10 @@
          point on the move. A value of 0 means no periodic scans will be used in the framework. -->
     <integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer>
 
+    <!-- Wifi driver stop delay, in milliseconds.
+         Default value is 2 minutes. -->
+    <integer translatable="false" name="config_wifi_driver_stop_delay">120000</integer>
+
     <!-- Flag indicating whether the keyguard should be bypassed when
          the slider is open.  This can be set or unset depending how easily
          the slider can be opened (for example, in a pocket or purse). -->
@@ -304,6 +308,9 @@
     <!-- If this is true, the screen will fade off. -->
     <bool name="config_animateScreenLights">true</bool>
 
+    <!-- If this is true, key chords can be used to take a screenshot on the device. -->
+    <bool name="config_enableScreenshotChord">true</bool>
+
     <!-- If true, the screen can be rotated via the accelerometer in all 4
          rotations as the default behavior. -->
     <bool name="config_allowAllRotations">false</bool>
@@ -628,6 +635,10 @@
                cell broadcasting sms, and MMS. -->
     <bool name="config_sms_capable">true</bool>
 
+    <!-- Enable/disable default bluetooth profiles:
+        HSP_AG, ObexObjectPush, Audio, NAP -->
+    <bool name="config_bluetooth_default_profiles">true</bool>
+
     <!-- IP address of the dns server to use if nobody else suggests one -->
     <string name="config_default_dns_server" translatable="false">8.8.8.8</string>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 047e6ed..e1bc33b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -244,6 +244,8 @@
   <java-symbol type="bool" name="config_useMasterVolume" />
   <java-symbol type="bool" name="config_enableWallpaperService" />
   <java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
+  <java-symbol type="bool" name="config_enableScreenshotChord" />
+  <java-symbol type="bool" name="config_bluetooth_default_profiles" />
 
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_longPressOnPowerBehavior" />
@@ -255,6 +257,7 @@
   <java-symbol type="integer" name="db_journal_size_limit" />
   <java-symbol type="integer" name="db_wal_autocheckpoint" />
   <java-symbol type="integer" name="max_action_buttons" />
+  <java-symbol type="integer" name="config_wifi_driver_stop_delay" />
 
   <java-symbol type="color" name="tab_indicator_text_v4" />
 
diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
index 2982816..0c31e2d 100755
--- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
@@ -24,6 +24,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StatFs;
+import android.os.UserId;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -674,7 +675,7 @@
             PackageDataObserver observer = new PackageDataObserver();
             //wait on observer
             synchronized(observer) {
-                getPm().clearApplicationUserData(packageName, observer);
+                getPm().clearApplicationUserData(packageName, observer, 0 /* TODO: Other users */);
                 long waitTime = 0;
                 while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) {
                     observer.wait(WAIT_TIME_INCR);
@@ -717,7 +718,8 @@
     
     File getDataDir() {
         try {
-            ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0);
+            ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0,
+                    UserId.myUserId());
             return new File(appInfo.dataDir);
         } catch (RemoteException e) {
             throw new RuntimeException("Pacakge manager dead", e);
@@ -746,7 +748,7 @@
     
     @LargeTest
     public void testClearApplicationUserDataNoObserver() throws Exception {
-        getPm().clearApplicationUserData(mContext.getPackageName(), null);
+        getPm().clearApplicationUserData(mContext.getPackageName(), null, UserId.myUserId());
         //sleep for 1 minute
         Thread.sleep(60*1000);
         //confirm files dont exist
diff --git a/data/fonts/vendor_fonts.xml b/data/fonts/vendor_fonts.xml
index c1116d0..5850f94 100644
--- a/data/fonts/vendor_fonts.xml
+++ b/data/fonts/vendor_fonts.xml
@@ -3,7 +3,12 @@
     Vendor-provided fallback fonts
 
     This file can be edited to add references to fonts that are not installed or referenced in the
-    default system. The file should then be placed in /vendor/etc/fallback_fonts.xml.
+    default system. The file should then be placed in /vendor/etc/fallback_fonts.xml. Note
+    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
 
     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
@@ -28,11 +33,31 @@
     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,
+    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.
+    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>
 
     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.
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 6539ff3..a76a628 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -131,22 +131,13 @@
     public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
 
     /**
-     * USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE The allocation
-     * will be used as a SurfaceTexture graphics consumer. This
-     * usage may only be used with USAGE_GRAPHICS_TEXTURE.
-     *
-     * @hide
-     */
-    public static final int USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE = 0x0020;
-
-    /**
      * USAGE_IO_INPUT The allocation will be used as SurfaceTexture
      * consumer.  This usage will cause the allocation to be created
      * read only.
      *
      * @hide
      */
-    public static final int USAGE_IO_INPUT = 0x0040;
+    public static final int USAGE_IO_INPUT = 0x0020;
 
     /**
      * USAGE_IO_OUTPUT The allocation will be used as a
@@ -155,7 +146,7 @@
      *
      * @hide
      */
-    public static final int USAGE_IO_OUTPUT = 0x0080;
+    public static final int USAGE_IO_OUTPUT = 0x0040;
 
     /**
      * Controls mipmap behavior when using the bitmap creation and
@@ -197,6 +188,40 @@
         return getID();
     }
 
+
+   /**
+     * Get the element of the type of the Allocation.
+     *
+     * @hide
+     * @return Element
+     *
+     */
+    public Element getElement() {
+        return mType.getElement();
+    }
+
+    /**
+     * Get the usage flags of the Allocation.
+     *
+     * @hide
+     * @return usage
+     *
+     */
+    public int getUsage() {
+        return mUsage;
+    }
+
+    /**
+     * Get the size of the Allocation in bytes.
+     *
+     * @hide
+     * @return sizeInBytes
+     *
+     */
+    public int getSizeBytes() {
+        return mType.getCount() * mType.getElement().getSizeBytes();
+    }
+
     private void updateCacheInfo(Type t) {
         mCurrentDimX = t.getX();
         mCurrentDimY = t.getY();
@@ -217,17 +242,15 @@
                        USAGE_GRAPHICS_VERTEX |
                        USAGE_GRAPHICS_CONSTANTS |
                        USAGE_GRAPHICS_RENDER_TARGET |
-                       USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
                        USAGE_IO_INPUT |
                        USAGE_IO_OUTPUT)) != 0) {
             throw new RSIllegalArgumentException("Unknown usage specified.");
         }
 
-        if ((usage & (USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE | USAGE_IO_INPUT)) != 0) {
+        if ((usage & USAGE_IO_INPUT) != 0) {
             mWriteAllowed = false;
 
-            if ((usage & ~(USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
-                           USAGE_IO_INPUT |
+            if ((usage & ~(USAGE_IO_INPUT |
                            USAGE_GRAPHICS_TEXTURE |
                            USAGE_SCRIPT)) != 0) {
                 throw new RSIllegalArgumentException("Invalid usage combination.");
@@ -305,10 +328,21 @@
         }
     }
 
+    /**
+     * Get the type of the Allocation.
+     *
+     * @return Type
+     *
+     */
     public Type getType() {
         return mType;
     }
 
+    /**
+     * Propagate changes from one usage of the allocation to the
+     * remaining usages of the allocation.
+     *
+     */
     public void syncAll(int srcLocation) {
         switch (srcLocation) {
         case USAGE_SCRIPT:
@@ -348,12 +382,17 @@
     public void ioGetInput() {
         if ((mUsage & USAGE_IO_INPUT) == 0) {
             throw new RSIllegalArgumentException(
-                "Can only send buffer if IO_OUTPUT usage specified.");
+                "Can only receive if IO_INPUT usage specified.");
         }
         mRS.validate();
         mRS.nAllocationIoReceive(getID());
     }
 
+    /**
+     * Copy an array of RS objects to the allocation.
+     *
+     * @param d Source array.
+     */
     public void copyFrom(BaseObj[] d) {
         mRS.validate();
         validateIsObject();
@@ -1134,13 +1173,15 @@
      *
      */
     public SurfaceTexture getSurfaceTexture() {
-        if ((mUsage & USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE) == 0) {
+        if ((mUsage & USAGE_IO_INPUT) == 0) {
             throw new RSInvalidStateException("Allocation is not a surface texture.");
         }
 
         int id = mRS.nAllocationGetSurfaceTextureID(getID());
-        return new SurfaceTexture(id);
+        SurfaceTexture st = new SurfaceTexture(id);
+        mRS.nAllocationGetSurfaceTextureID2(getID(), st);
 
+        return st;
     }
 
     /**
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 6921f37..ab6ba54 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -16,8 +16,8 @@
 
 package android.renderscript;
 
-import java.lang.reflect.Field;
 import java.io.File;
+import java.lang.reflect.Field;
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -294,6 +294,11 @@
         validate();
         return rsnAllocationGetSurfaceTextureID(mContext, alloc);
     }
+    native void rsnAllocationGetSurfaceTextureID2(int con, int alloc, SurfaceTexture st);
+    synchronized void nAllocationGetSurfaceTextureID2(int alloc, SurfaceTexture st) {
+        validate();
+        rsnAllocationGetSurfaceTextureID2(mContext, alloc, st);
+    }
     native void rsnAllocationSetSurfaceTexture(int con, int alloc, SurfaceTexture sur);
     synchronized void nAllocationSetSurfaceTexture(int alloc, SurfaceTexture sur) {
         validate();
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 9fc4fd4..9d4c64f 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -477,6 +477,15 @@
 }
 
 static void
+nAllocationGetSurfaceTextureID2(JNIEnv *_env, jobject _this, RsContext con, jint a, jobject jst)
+{
+    LOG_API("nAllocationGetSurfaceTextureID2, con(%p), a(%p)", con, (RsAllocation)a);
+    sp<SurfaceTexture> st = SurfaceTexture_getSurfaceTexture(_env, jst);
+
+    rsAllocationGetSurfaceTextureID2(con, (RsAllocation)a, st.get(), sizeof(SurfaceTexture *));
+}
+
+static void
 nAllocationSetSurfaceTexture(JNIEnv *_env, jobject _this, RsContext con,
                              RsAllocation alloc, jobject sur)
 {
@@ -1352,7 +1361,8 @@
 
 {"rsnAllocationSyncAll",             "(III)V",                                (void*)nAllocationSyncAll },
 {"rsnAllocationGetSurfaceTextureID", "(II)I",                                 (void*)nAllocationGetSurfaceTextureID },
-{"rsnAllocationSetSurfaceTexture",   "(IILandroid/graphics/SurfaceTexture;)V", (void*)nAllocationSetSurfaceTexture },
+{"rsnAllocationGetSurfaceTextureID2","(IILandroid/graphics/SurfaceTexture;)V",(void*)nAllocationGetSurfaceTextureID2 },
+{"rsnAllocationSetSurfaceTexture",   "(IILandroid/graphics/SurfaceTexture;)V",(void*)nAllocationSetSurfaceTexture },
 {"rsnAllocationIoSend",              "(II)V",                                 (void*)nAllocationIoSend },
 {"rsnAllocationIoReceive",           "(II)V",                                 (void*)nAllocationIoReceive },
 {"rsnAllocationData1D",              "(IIIII[II)V",                           (void*)nAllocationData1D_i },
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index d95b45e..d153c31 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -22,13 +22,13 @@
 
 #include <androidfw/Asset.h>
 #include <androidfw/AssetDir.h>
-#include <androidfw/ZipFileRO.h>
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
 #include <utils/String16.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
 #include <utils/Vector.h>
+#include <utils/ZipFileRO.h>
 
 /*
  * Native-app access is via the opaque typedef struct AAssetManager in the C namespace.
diff --git a/include/androidfw/ZipFileCRO.h b/include/androidfw/ZipFileCRO.h
deleted file mode 100644
index 3e42a95..0000000
--- a/include/androidfw/ZipFileCRO.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-// C API for ead-only access to Zip archives, with minimal heap allocation.
-//
-#ifndef __LIBS_ZIPFILECRO_H
-#define __LIBS_ZIPFILECRO_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <utils/Compat.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Trivial typedef to ensure that ZipFileCRO is not treated as a simple integer.
- */
-typedef void* ZipFileCRO;
-
-/*
- * Trivial typedef to ensure that ZipEntryCRO is not treated as a simple
- * integer.  We use NULL to indicate an invalid value.
- */
-typedef void* ZipEntryCRO;
-
-extern ZipFileCRO ZipFileXRO_open(const char* path);
-
-extern void ZipFileCRO_destroy(ZipFileCRO zip);
-
-extern ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zip,
-        const char* fileName);
-
-extern bool ZipFileCRO_getEntryInfo(ZipFileCRO zip, ZipEntryCRO entry,
-        int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32);
-
-extern bool ZipFileCRO_uncompressEntry(ZipFileCRO zip, ZipEntryCRO entry, int fd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*__LIBS_ZIPFILECRO_H*/
diff --git a/include/androidfw/ZipFileRO.h b/include/androidfw/ZipFileRO.h
deleted file mode 100644
index 547e36a..0000000
--- a/include/androidfw/ZipFileRO.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-/*
- * Read-only access to Zip archives, with minimal heap allocation.
- *
- * This is similar to the more-complete ZipFile class, but no attempt
- * has been made to make them interchangeable.  This class operates under
- * a very different set of assumptions and constraints.
- *
- * One such assumption is that if you're getting file descriptors for
- * use with this class as a child of a fork() operation, you must be on
- * a pread() to guarantee correct operation. This is because pread() can
- * atomically read at a file offset without worrying about a lock around an
- * lseek() + read() pair.
- */
-#ifndef __LIBS_ZIPFILERO_H
-#define __LIBS_ZIPFILERO_H
-
-#include <utils/Compat.h>
-#include <utils/Errors.h>
-#include <utils/FileMap.h>
-#include <utils/threads.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-
-namespace android {
-
-/*
- * Trivial typedef to ensure that ZipEntryRO is not treated as a simple
- * integer.  We use NULL to indicate an invalid value.
- */
-typedef void* ZipEntryRO;
-
-/*
- * Open a Zip archive for reading.
- *
- * We want "open" and "find entry by name" to be fast operations, and we
- * want to use as little memory as possible.  We memory-map the file,
- * and load a hash table with pointers to the filenames (which aren't
- * null-terminated).  The other fields are at a fixed offset from the
- * filename, so we don't need to extract those (but we do need to byte-read
- * and endian-swap them every time we want them).
- *
- * To speed comparisons when doing a lookup by name, we could make the mapping
- * "private" (copy-on-write) and null-terminate the filenames after verifying
- * the record structure.  However, this requires a private mapping of
- * every page that the Central Directory touches.  Easier to tuck a copy
- * of the string length into the hash table entry.
- *
- * NOTE: If this is used on file descriptors inherited from a fork() operation,
- * you must be on a platform that implements pread() to guarantee correctness
- * on the shared file descriptors.
- */
-class ZipFileRO {
-public:
-    ZipFileRO()
-        : mFd(-1), mFileName(NULL), mFileLength(-1),
-          mDirectoryMap(NULL),
-          mNumEntries(-1), mDirectoryOffset(-1),
-          mHashTableSize(-1), mHashTable(NULL)
-        {}
-
-    ~ZipFileRO();
-
-    /*
-     * Open an archive.
-     */
-    status_t open(const char* zipFileName);
-
-    /*
-     * Find an entry, by name.  Returns the entry identifier, or NULL if
-     * not found.
-     *
-     * If two entries have the same name, one will be chosen at semi-random.
-     */
-    ZipEntryRO findEntryByName(const char* fileName) const;
-
-    /*
-     * Return the #of entries in the Zip archive.
-     */
-    int getNumEntries(void) const {
-        return mNumEntries;
-    }
-
-    /*
-     * Return the Nth entry.  Zip file entries are not stored in sorted
-     * order, and updated entries may appear at the end, so anyone walking
-     * the archive needs to avoid making ordering assumptions.  We take
-     * that further by returning the Nth non-empty entry in the hash table
-     * rather than the Nth entry in the archive.
-     *
-     * Valid values are [0..numEntries).
-     *
-     * [This is currently O(n).  If it needs to be fast we can allocate an
-     * additional data structure or provide an iterator interface.]
-     */
-    ZipEntryRO findEntryByIndex(int idx) const;
-
-    /*
-     * Copy the filename into the supplied buffer.  Returns 0 on success,
-     * -1 if "entry" is invalid, or the filename length if it didn't fit.  The
-     * length, and the returned string, include the null-termination.
-     */
-    int getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen) const;
-
-    /*
-     * Get the vital stats for an entry.  Pass in NULL pointers for anything
-     * you don't need.
-     *
-     * "*pOffset" holds the Zip file offset of the entry's data.
-     *
-     * Returns "false" if "entry" is bogus or if the data in the Zip file
-     * appears to be bad.
-     */
-    bool getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const;
-
-    /*
-     * Create a new FileMap object that maps a subset of the archive.  For
-     * an uncompressed entry this effectively provides a pointer to the
-     * actual data, for a compressed entry this provides the input buffer
-     * for inflate().
-     */
-    FileMap* createEntryFileMap(ZipEntryRO entry) const;
-
-    /*
-     * Uncompress the data into a buffer.  Depending on the compression
-     * format, this is either an "inflate" operation or a memcpy.
-     *
-     * Use "uncompLen" from getEntryInfo() to determine the required
-     * buffer size.
-     *
-     * Returns "true" on success.
-     */
-    bool uncompressEntry(ZipEntryRO entry, void* buffer) const;
-
-    /*
-     * Uncompress the data to an open file descriptor.
-     */
-    bool uncompressEntry(ZipEntryRO entry, int fd) const;
-
-    /* Zip compression methods we support */
-    enum {
-        kCompressStored     = 0,        // no compression
-        kCompressDeflated   = 8,        // standard deflate
-    };
-
-    /*
-     * Utility function: uncompress deflated data, buffer to buffer.
-     */
-    static bool inflateBuffer(void* outBuf, const void* inBuf,
-        size_t uncompLen, size_t compLen);
-
-    /*
-     * Utility function: uncompress deflated data, buffer to fd.
-     */
-    static bool inflateBuffer(int fd, const void* inBuf,
-        size_t uncompLen, size_t compLen);
-
-    /*
-     * Utility function to convert ZIP's time format to a timespec struct.
-     */
-    static inline void zipTimeToTimespec(long when, struct tm* timespec) {
-        const long date = when >> 16;
-        timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980
-        timespec->tm_mon = (date >> 5) & 0x0F;
-        timespec->tm_mday = date & 0x1F;
-
-        timespec->tm_hour = (when >> 11) & 0x1F;
-        timespec->tm_min = (when >> 5) & 0x3F;
-        timespec->tm_sec = (when & 0x1F) << 1;
-    }
-
-    /*
-     * Some basic functions for raw data manipulation.  "LE" means
-     * Little Endian.
-     */
-    static inline unsigned short get2LE(const unsigned char* buf) {
-        return buf[0] | (buf[1] << 8);
-    }
-    static inline unsigned long get4LE(const unsigned char* buf) {
-        return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
-    }
-
-private:
-    /* these are private and not defined */ 
-    ZipFileRO(const ZipFileRO& src);
-    ZipFileRO& operator=(const ZipFileRO& src);
-
-    /* locate and parse the central directory */
-    bool mapCentralDirectory(void);
-
-    /* parse the archive, prepping internal structures */
-    bool parseZipArchive(void);
-
-    /* add a new entry to the hash table */
-    void addToHash(const char* str, int strLen, unsigned int hash);
-
-    /* compute string hash code */
-    static unsigned int computeHash(const char* str, int len);
-
-    /* convert a ZipEntryRO back to a hash table index */
-    int entryToIndex(const ZipEntryRO entry) const;
-
-    /*
-     * One entry in the hash table.
-     */
-    typedef struct HashEntry {
-        const char*     name;
-        unsigned short  nameLen;
-        //unsigned int    hash;
-    } HashEntry;
-
-    /* open Zip archive */
-    int         mFd;
-
-    /* Lock for handling the file descriptor (seeks, etc) */
-    mutable Mutex mFdLock;
-
-    /* zip file name */
-    char*       mFileName;
-
-    /* length of file */
-    size_t      mFileLength;
-
-    /* mapped file */
-    FileMap*    mDirectoryMap;
-
-    /* number of entries in the Zip archive */
-    int         mNumEntries;
-
-    /* CD directory offset in the Zip archive */
-    off64_t     mDirectoryOffset;
-
-    /*
-     * We know how many entries are in the Zip archive, so we have a
-     * fixed-size hash table.  We probe for an empty slot.
-     */
-    int         mHashTableSize;
-    HashEntry*  mHashTable;
-};
-
-}; // namespace android
-
-#endif /*__LIBS_ZIPFILERO_H*/
diff --git a/include/androidfw/ZipUtils.h b/include/androidfw/ZipUtils.h
deleted file mode 100644
index 42c42b6..0000000
--- a/include/androidfw/ZipUtils.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-//
-// Miscellaneous zip/gzip utility functions.
-//
-#ifndef __LIBS_ZIPUTILS_H
-#define __LIBS_ZIPUTILS_H
-
-#include <stdio.h>
-
-namespace android {
-
-/*
- * Container class for utility functions, primarily for namespace reasons.
- */
-class ZipUtils {
-public:
-    /*
-     * General utility function for uncompressing "deflate" data from a file
-     * to a buffer.
-     */
-    static bool inflateToBuffer(int fd, void* buf, long uncompressedLen,
-        long compressedLen);
-    static bool inflateToBuffer(FILE* fp, void* buf, long uncompressedLen,
-        long compressedLen);
-
-    /*
-     * Someday we might want to make this generic and handle bzip2 ".bz2"
-     * files too.
-     *
-     * We could declare gzip to be a sub-class of zip that has exactly
-     * one always-compressed entry, but we currently want to treat Zip
-     * and gzip as distinct, so there's no value.
-     *
-     * The zlib library has some gzip utilities, but it has no interface
-     * for extracting the uncompressed length of the file (you do *not*
-     * want to gzseek to the end).
-     *
-     * Pass in a seeked file pointer for the gzip file.  If this is a gzip
-     * file, we set our return values appropriately and return "true" with
-     * the file seeked to the start of the compressed data.
-     */
-    static bool examineGzip(FILE* fp, int* pCompressionMethod,
-        long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32);
-
-private:
-    ZipUtils() {}
-    ~ZipUtils() {}
-};
-
-}; // namespace android
-
-#endif /*__LIBS_ZIPUTILS_H*/
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index 4e89d87..a3f92cb 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -24,10 +24,7 @@
     AssetManager.cpp \
     ObbFile.cpp \
     ResourceTypes.cpp \
-    StreamingZipInflater.cpp \
-    ZipFileCRO.cpp \
-    ZipFileRO.cpp \
-    ZipUtils.cpp
+    StreamingZipInflater.cpp
 
 # formerly in libui
 commonUiSources:= \
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index cb7628d..fd5b3e4 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -23,11 +23,11 @@
 
 #include <androidfw/Asset.h>
 #include <androidfw/StreamingZipInflater.h>
-#include <androidfw/ZipFileRO.h>
-#include <androidfw/ZipUtils.h>
 #include <utils/Atomic.h>
 #include <utils/FileMap.h>
 #include <utils/Log.h>
+#include <utils/ZipFileRO.h>
+#include <utils/ZipUtils.h>
 #include <utils/threads.h>
 
 #include <assert.h>
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 4829add..8d59d8e 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -25,13 +25,13 @@
 #include <androidfw/AssetDir.h>
 #include <androidfw/AssetManager.h>
 #include <androidfw/ResourceTypes.h>
-#include <androidfw/ZipFileRO.h>
 #include <utils/Atomic.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
 #include <utils/Timers.h>
+#include <utils/ZipFileRO.h>
 
 #include <assert.h>
 #include <dirent.h>
diff --git a/libs/androidfw/ZipFileCRO.cpp b/libs/androidfw/ZipFileCRO.cpp
deleted file mode 100644
index c8df845..0000000
--- a/libs/androidfw/ZipFileCRO.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <androidfw/ZipFileCRO.h>
-#include <androidfw/ZipFileRO.h>
-
-using namespace android;
-
-ZipFileCRO ZipFileXRO_open(const char* path) {
-    ZipFileRO* zip = new ZipFileRO();
-    if (zip->open(path) == NO_ERROR) {
-        return (ZipFileCRO)zip;
-    }
-    return NULL;
-}
-
-void ZipFileCRO_destroy(ZipFileCRO zipToken) {
-    ZipFileRO* zip = (ZipFileRO*)zipToken;
-    delete zip;
-}
-
-ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zipToken,
-        const char* fileName) {
-    ZipFileRO* zip = (ZipFileRO*)zipToken;
-    return (ZipEntryCRO)zip->findEntryByName(fileName);
-}
-
-bool ZipFileCRO_getEntryInfo(ZipFileCRO zipToken, ZipEntryRO entryToken,
-        int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) {
-    ZipFileRO* zip = (ZipFileRO*)zipToken;
-    ZipEntryRO entry = (ZipEntryRO)entryToken;
-    return zip->getEntryInfo(entry, pMethod, pUncompLen, pCompLen, pOffset,
-            pModWhen, pCrc32);
-}
-
-bool ZipFileCRO_uncompressEntry(ZipFileCRO zipToken, ZipEntryRO entryToken, int fd) {
-    ZipFileRO* zip = (ZipFileRO*)zipToken;
-    ZipEntryRO entry = (ZipEntryRO)entryToken;
-    return zip->uncompressEntry(entry, fd);
-}
diff --git a/libs/androidfw/ZipFileRO.cpp b/libs/androidfw/ZipFileRO.cpp
deleted file mode 100644
index 4b7f1e7..0000000
--- a/libs/androidfw/ZipFileRO.cpp
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-//
-// Read-only access to Zip archives, with minimal heap allocation.
-//
-#define LOG_TAG "zipro"
-//#define LOG_NDEBUG 0
-#include <androidfw/ZipFileRO.h>
-#include <utils/Log.h>
-#include <utils/misc.h>
-#include <utils/threads.h>
-
-#include <zlib.h>
-
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <assert.h>
-#include <unistd.h>
-
-#if HAVE_PRINTF_ZD
-#  define ZD "%zd"
-#  define ZD_TYPE ssize_t
-#else
-#  define ZD "%ld"
-#  define ZD_TYPE long
-#endif
-
-/*
- * We must open binary files using open(path, ... | O_BINARY) under Windows.
- * Otherwise strange read errors will happen.
- */
-#ifndef O_BINARY
-#  define O_BINARY  0
-#endif
-
-/*
- * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
- * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
- * not already defined, then define it here.
- */
-#ifndef TEMP_FAILURE_RETRY
-/* Used to retry syscalls that can return EINTR. */
-#define TEMP_FAILURE_RETRY(exp) ({         \
-    typeof (exp) _rc;                      \
-    do {                                   \
-        _rc = (exp);                       \
-    } while (_rc == -1 && errno == EINTR); \
-    _rc; })
-#endif
-
-using namespace android;
-
-/*
- * Zip file constants.
- */
-#define kEOCDSignature      0x06054b50
-#define kEOCDLen            22
-#define kEOCDNumEntries     8               // offset to #of entries in file
-#define kEOCDSize           12              // size of the central directory
-#define kEOCDFileOffset     16              // offset to central directory
-
-#define kMaxCommentLen      65535           // longest possible in ushort
-#define kMaxEOCDSearch      (kMaxCommentLen + kEOCDLen)
-
-#define kLFHSignature       0x04034b50
-#define kLFHLen             30              // excluding variable-len fields
-#define kLFHNameLen         26              // offset to filename length
-#define kLFHExtraLen        28              // offset to extra length
-
-#define kCDESignature       0x02014b50
-#define kCDELen             46              // excluding variable-len fields
-#define kCDEMethod          10              // offset to compression method
-#define kCDEModWhen         12              // offset to modification timestamp
-#define kCDECRC             16              // offset to entry CRC
-#define kCDECompLen         20              // offset to compressed length
-#define kCDEUncompLen       24              // offset to uncompressed length
-#define kCDENameLen         28              // offset to filename length
-#define kCDEExtraLen        30              // offset to extra length
-#define kCDECommentLen      32              // offset to comment length
-#define kCDELocalOffset     42              // offset to local hdr
-
-/*
- * The values we return for ZipEntryRO use 0 as an invalid value, so we
- * want to adjust the hash table index by a fixed amount.  Using a large
- * value helps insure that people don't mix & match arguments, e.g. to
- * findEntryByIndex().
- */
-#define kZipEntryAdj        10000
-
-ZipFileRO::~ZipFileRO() {
-    free(mHashTable);
-    if (mDirectoryMap)
-        mDirectoryMap->release();
-    if (mFd >= 0)
-        TEMP_FAILURE_RETRY(close(mFd));
-    if (mFileName)
-        free(mFileName);
-}
-
-/*
- * Convert a ZipEntryRO to a hash table index, verifying that it's in a
- * valid range.
- */
-int ZipFileRO::entryToIndex(const ZipEntryRO entry) const
-{
-    long ent = ((long) entry) - kZipEntryAdj;
-    if (ent < 0 || ent >= mHashTableSize || mHashTable[ent].name == NULL) {
-        ALOGW("Invalid ZipEntryRO %p (%ld)\n", entry, ent);
-        return -1;
-    }
-    return ent;
-}
-
-
-/*
- * Open the specified file read-only.  We memory-map the entire thing and
- * close the file before returning.
- */
-status_t ZipFileRO::open(const char* zipFileName)
-{
-    int fd = -1;
-
-    assert(mDirectoryMap == NULL);
-
-    /*
-     * Open and map the specified file.
-     */
-    fd = ::open(zipFileName, O_RDONLY | O_BINARY);
-    if (fd < 0) {
-        ALOGW("Unable to open zip '%s': %s\n", zipFileName, strerror(errno));
-        return NAME_NOT_FOUND;
-    }
-
-    mFileLength = lseek64(fd, 0, SEEK_END);
-    if (mFileLength < kEOCDLen) {
-        TEMP_FAILURE_RETRY(close(fd));
-        return UNKNOWN_ERROR;
-    }
-
-    if (mFileName != NULL) {
-        free(mFileName);
-    }
-    mFileName = strdup(zipFileName);
-
-    mFd = fd;
-
-    /*
-     * Find the Central Directory and store its size and number of entries.
-     */
-    if (!mapCentralDirectory()) {
-        goto bail;
-    }
-
-    /*
-     * Verify Central Directory and create data structures for fast access.
-     */
-    if (!parseZipArchive()) {
-        goto bail;
-    }
-
-    return OK;
-
-bail:
-    free(mFileName);
-    mFileName = NULL;
-    TEMP_FAILURE_RETRY(close(fd));
-    return UNKNOWN_ERROR;
-}
-
-/*
- * Parse the Zip archive, verifying its contents and initializing internal
- * data structures.
- */
-bool ZipFileRO::mapCentralDirectory(void)
-{
-    ssize_t readAmount = kMaxEOCDSearch;
-    if (readAmount > (ssize_t) mFileLength)
-        readAmount = mFileLength;
-
-    unsigned char* scanBuf = (unsigned char*) malloc(readAmount);
-    if (scanBuf == NULL) {
-        ALOGW("couldn't allocate scanBuf: %s", strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-
-    /*
-     * Make sure this is a Zip archive.
-     */
-    if (lseek64(mFd, 0, SEEK_SET) != 0) {
-        ALOGW("seek to start failed: %s", strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-
-    ssize_t actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, sizeof(int32_t)));
-    if (actual != (ssize_t) sizeof(int32_t)) {
-        ALOGI("couldn't read first signature from zip archive: %s", strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-
-    {
-        unsigned int header = get4LE(scanBuf);
-        if (header == kEOCDSignature) {
-            ALOGI("Found Zip archive, but it looks empty\n");
-            free(scanBuf);
-            return false;
-        } else if (header != kLFHSignature) {
-            ALOGV("Not a Zip archive (found 0x%08x)\n", header);
-            free(scanBuf);
-            return false;
-        }
-    }
-
-    /*
-     * Perform the traditional EOCD snipe hunt.
-     *
-     * We're searching for the End of Central Directory magic number,
-     * which appears at the start of the EOCD block.  It's followed by
-     * 18 bytes of EOCD stuff and up to 64KB of archive comment.  We
-     * need to read the last part of the file into a buffer, dig through
-     * it to find the magic number, parse some values out, and use those
-     * to determine the extent of the CD.
-     *
-     * We start by pulling in the last part of the file.
-     */
-    off64_t searchStart = mFileLength - readAmount;
-
-    if (lseek64(mFd, searchStart, SEEK_SET) != searchStart) {
-        ALOGW("seek %ld failed: %s\n",  (long) searchStart, strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-    actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, readAmount));
-    if (actual != (ssize_t) readAmount) {
-        ALOGW("Zip: read " ZD ", expected " ZD ". Failed: %s\n",
-            (ZD_TYPE) actual, (ZD_TYPE) readAmount, strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-
-    /*
-     * Scan backward for the EOCD magic.  In an archive without a trailing
-     * comment, we'll find it on the first try.  (We may want to consider
-     * doing an initial minimal read; if we don't find it, retry with a
-     * second read as above.)
-     */
-    int i;
-    for (i = readAmount - kEOCDLen; i >= 0; i--) {
-        if (scanBuf[i] == 0x50 && get4LE(&scanBuf[i]) == kEOCDSignature) {
-            ALOGV("+++ Found EOCD at buf+%d\n", i);
-            break;
-        }
-    }
-    if (i < 0) {
-        ALOGD("Zip: EOCD not found, %s is not zip\n", mFileName);
-        free(scanBuf);
-        return false;
-    }
-
-    off64_t eocdOffset = searchStart + i;
-    const unsigned char* eocdPtr = scanBuf + i;
-
-    assert(eocdOffset < mFileLength);
-
-    /*
-     * Grab the CD offset and size, and the number of entries in the
-     * archive. After that, we can release our EOCD hunt buffer.
-     */
-    unsigned int numEntries = get2LE(eocdPtr + kEOCDNumEntries);
-    unsigned int dirSize = get4LE(eocdPtr + kEOCDSize);
-    unsigned int dirOffset = get4LE(eocdPtr + kEOCDFileOffset);
-    free(scanBuf);
-
-    // Verify that they look reasonable.
-    if ((long long) dirOffset + (long long) dirSize > (long long) eocdOffset) {
-        ALOGW("bad offsets (dir %ld, size %u, eocd %ld)\n",
-            (long) dirOffset, dirSize, (long) eocdOffset);
-        return false;
-    }
-    if (numEntries == 0) {
-        ALOGW("empty archive?\n");
-        return false;
-    }
-
-    ALOGV("+++ numEntries=%d dirSize=%d dirOffset=%d\n",
-        numEntries, dirSize, dirOffset);
-
-    mDirectoryMap = new FileMap();
-    if (mDirectoryMap == NULL) {
-        ALOGW("Unable to create directory map: %s", strerror(errno));
-        return false;
-    }
-
-    if (!mDirectoryMap->create(mFileName, mFd, dirOffset, dirSize, true)) {
-        ALOGW("Unable to map '%s' (" ZD " to " ZD "): %s\n", mFileName,
-                (ZD_TYPE) dirOffset, (ZD_TYPE) (dirOffset + dirSize), strerror(errno));
-        return false;
-    }
-
-    mNumEntries = numEntries;
-    mDirectoryOffset = dirOffset;
-
-    return true;
-}
-
-bool ZipFileRO::parseZipArchive(void)
-{
-    bool result = false;
-    const unsigned char* cdPtr = (const unsigned char*) mDirectoryMap->getDataPtr();
-    size_t cdLength = mDirectoryMap->getDataLength();
-    int numEntries = mNumEntries;
-
-    /*
-     * Create hash table.  We have a minimum 75% load factor, possibly as
-     * low as 50% after we round off to a power of 2.
-     */
-    mHashTableSize = roundUpPower2(1 + (numEntries * 4) / 3);
-    mHashTable = (HashEntry*) calloc(mHashTableSize, sizeof(HashEntry));
-
-    /*
-     * Walk through the central directory, adding entries to the hash
-     * table.
-     */
-    const unsigned char* ptr = cdPtr;
-    for (int i = 0; i < numEntries; i++) {
-        if (get4LE(ptr) != kCDESignature) {
-            ALOGW("Missed a central dir sig (at %d)\n", i);
-            goto bail;
-        }
-        if (ptr + kCDELen > cdPtr + cdLength) {
-            ALOGW("Ran off the end (at %d)\n", i);
-            goto bail;
-        }
-
-        long localHdrOffset = (long) get4LE(ptr + kCDELocalOffset);
-        if (localHdrOffset >= mDirectoryOffset) {
-            ALOGW("bad LFH offset %ld at entry %d\n", localHdrOffset, i);
-            goto bail;
-        }
-
-        unsigned int fileNameLen, extraLen, commentLen, hash;
-
-        fileNameLen = get2LE(ptr + kCDENameLen);
-        extraLen = get2LE(ptr + kCDEExtraLen);
-        commentLen = get2LE(ptr + kCDECommentLen);
-
-        /* add the CDE filename to the hash table */
-        hash = computeHash((const char*)ptr + kCDELen, fileNameLen);
-        addToHash((const char*)ptr + kCDELen, fileNameLen, hash);
-
-        ptr += kCDELen + fileNameLen + extraLen + commentLen;
-        if ((size_t)(ptr - cdPtr) > cdLength) {
-            ALOGW("bad CD advance (%d vs " ZD ") at entry %d\n",
-                (int) (ptr - cdPtr), (ZD_TYPE) cdLength, i);
-            goto bail;
-        }
-    }
-    ALOGV("+++ zip good scan %d entries\n", numEntries);
-    result = true;
-
-bail:
-    return result;
-}
-
-/*
- * Simple string hash function for non-null-terminated strings.
- */
-/*static*/ unsigned int ZipFileRO::computeHash(const char* str, int len)
-{
-    unsigned int hash = 0;
-
-    while (len--)
-        hash = hash * 31 + *str++;
-
-    return hash;
-}
-
-/*
- * Add a new entry to the hash table.
- */
-void ZipFileRO::addToHash(const char* str, int strLen, unsigned int hash)
-{
-    int ent = hash & (mHashTableSize-1);
-
-    /*
-     * We over-allocate the table, so we're guaranteed to find an empty slot.
-     */
-    while (mHashTable[ent].name != NULL)
-        ent = (ent + 1) & (mHashTableSize-1);
-
-    mHashTable[ent].name = str;
-    mHashTable[ent].nameLen = strLen;
-}
-
-/*
- * Find a matching entry.
- *
- * Returns NULL if not found.
- */
-ZipEntryRO ZipFileRO::findEntryByName(const char* fileName) const
-{
-    /*
-     * If the ZipFileRO instance is not initialized, the entry number will
-     * end up being garbage since mHashTableSize is -1.
-     */
-    if (mHashTableSize <= 0) {
-        return NULL;
-    }
-
-    int nameLen = strlen(fileName);
-    unsigned int hash = computeHash(fileName, nameLen);
-    int ent = hash & (mHashTableSize-1);
-
-    while (mHashTable[ent].name != NULL) {
-        if (mHashTable[ent].nameLen == nameLen &&
-            memcmp(mHashTable[ent].name, fileName, nameLen) == 0)
-        {
-            /* match */
-            return (ZipEntryRO)(long)(ent + kZipEntryAdj);
-        }
-
-        ent = (ent + 1) & (mHashTableSize-1);
-    }
-
-    return NULL;
-}
-
-/*
- * Find the Nth entry.
- *
- * This currently involves walking through the sparse hash table, counting
- * non-empty entries.  If we need to speed this up we can either allocate
- * a parallel lookup table or (perhaps better) provide an iterator interface.
- */
-ZipEntryRO ZipFileRO::findEntryByIndex(int idx) const
-{
-    if (idx < 0 || idx >= mNumEntries) {
-        ALOGW("Invalid index %d\n", idx);
-        return NULL;
-    }
-
-    for (int ent = 0; ent < mHashTableSize; ent++) {
-        if (mHashTable[ent].name != NULL) {
-            if (idx-- == 0)
-                return (ZipEntryRO) (ent + kZipEntryAdj);
-        }
-    }
-
-    return NULL;
-}
-
-/*
- * Get the useful fields from the zip entry.
- *
- * Returns "false" if the offsets to the fields or the contents of the fields
- * appear to be bogus.
- */
-bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
-    size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const
-{
-    bool ret = false;
-
-    const int ent = entryToIndex(entry);
-    if (ent < 0)
-        return false;
-
-    HashEntry hashEntry = mHashTable[ent];
-
-    /*
-     * Recover the start of the central directory entry from the filename
-     * pointer.  The filename is the first entry past the fixed-size data,
-     * so we can just subtract back from that.
-     */
-    const unsigned char* ptr = (const unsigned char*) hashEntry.name;
-    off64_t cdOffset = mDirectoryOffset;
-
-    ptr -= kCDELen;
-
-    int method = get2LE(ptr + kCDEMethod);
-    if (pMethod != NULL)
-        *pMethod = method;
-
-    if (pModWhen != NULL)
-        *pModWhen = get4LE(ptr + kCDEModWhen);
-    if (pCrc32 != NULL)
-        *pCrc32 = get4LE(ptr + kCDECRC);
-
-    size_t compLen = get4LE(ptr + kCDECompLen);
-    if (pCompLen != NULL)
-        *pCompLen = compLen;
-    size_t uncompLen = get4LE(ptr + kCDEUncompLen);
-    if (pUncompLen != NULL)
-        *pUncompLen = uncompLen;
-
-    /*
-     * If requested, determine the offset of the start of the data.  All we
-     * have is the offset to the Local File Header, which is variable size,
-     * so we have to read the contents of the struct to figure out where
-     * the actual data starts.
-     *
-     * We also need to make sure that the lengths are not so large that
-     * somebody trying to map the compressed or uncompressed data runs
-     * off the end of the mapped region.
-     *
-     * Note we don't verify compLen/uncompLen if they don't request the
-     * dataOffset, because dataOffset is expensive to determine.  However,
-     * if they don't have the file offset, they're not likely to be doing
-     * anything with the contents.
-     */
-    if (pOffset != NULL) {
-        long localHdrOffset = get4LE(ptr + kCDELocalOffset);
-        if (localHdrOffset + kLFHLen >= cdOffset) {
-            ALOGE("ERROR: bad local hdr offset in zip\n");
-            return false;
-        }
-
-        unsigned char lfhBuf[kLFHLen];
-
-#ifdef HAVE_PREAD
-        /*
-         * This file descriptor might be from zygote's preloaded assets,
-         * so we need to do an pread64() instead of a lseek64() + read() to
-         * guarantee atomicity across the processes with the shared file
-         * descriptors.
-         */
-        ssize_t actual =
-                TEMP_FAILURE_RETRY(pread64(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset));
-
-        if (actual != sizeof(lfhBuf)) {
-            ALOGW("failed reading lfh from offset %ld\n", localHdrOffset);
-            return false;
-        }
-
-        if (get4LE(lfhBuf) != kLFHSignature) {
-            ALOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; "
-                    "got: data=0x%08lx\n",
-                    localHdrOffset, kLFHSignature, get4LE(lfhBuf));
-            return false;
-        }
-#else /* HAVE_PREAD */
-        /*
-         * For hosts don't have pread64() we cannot guarantee atomic reads from
-         * an offset in a file. Android should never run on those platforms.
-         * File descriptors inherited from a fork() share file offsets and
-         * there would be nothing to protect from two different processes
-         * calling lseek64() concurrently.
-         */
-
-        {
-            AutoMutex _l(mFdLock);
-
-            if (lseek64(mFd, localHdrOffset, SEEK_SET) != localHdrOffset) {
-                ALOGW("failed seeking to lfh at offset %ld\n", localHdrOffset);
-                return false;
-            }
-
-            ssize_t actual =
-                    TEMP_FAILURE_RETRY(read(mFd, lfhBuf, sizeof(lfhBuf)));
-            if (actual != sizeof(lfhBuf)) {
-                ALOGW("failed reading lfh from offset %ld\n", localHdrOffset);
-                return false;
-            }
-
-            if (get4LE(lfhBuf) != kLFHSignature) {
-                off64_t actualOffset = lseek64(mFd, 0, SEEK_CUR);
-                ALOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; "
-                        "got: offset=" ZD " data=0x%08lx\n",
-                        localHdrOffset, kLFHSignature, (ZD_TYPE) actualOffset, get4LE(lfhBuf));
-                return false;
-            }
-        }
-#endif /* HAVE_PREAD */
-
-        off64_t dataOffset = localHdrOffset + kLFHLen
-            + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen);
-        if (dataOffset >= cdOffset) {
-            ALOGW("bad data offset %ld in zip\n", (long) dataOffset);
-            return false;
-        }
-
-        /* check lengths */
-        if ((off64_t)(dataOffset + compLen) > cdOffset) {
-            ALOGW("bad compressed length in zip (%ld + " ZD " > %ld)\n",
-                (long) dataOffset, (ZD_TYPE) compLen, (long) cdOffset);
-            return false;
-        }
-
-        if (method == kCompressStored &&
-            (off64_t)(dataOffset + uncompLen) > cdOffset)
-        {
-            ALOGE("ERROR: bad uncompressed length in zip (%ld + " ZD " > %ld)\n",
-                (long) dataOffset, (ZD_TYPE) uncompLen, (long) cdOffset);
-            return false;
-        }
-
-        *pOffset = dataOffset;
-    }
-
-    return true;
-}
-
-/*
- * Copy the entry's filename to the buffer.
- */
-int ZipFileRO::getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen)
-    const
-{
-    int ent = entryToIndex(entry);
-    if (ent < 0)
-        return -1;
-
-    int nameLen = mHashTable[ent].nameLen;
-    if (bufLen < nameLen+1)
-        return nameLen+1;
-
-    memcpy(buffer, mHashTable[ent].name, nameLen);
-    buffer[nameLen] = '\0';
-    return 0;
-}
-
-/*
- * Create a new FileMap object that spans the data in "entry".
- */
-FileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const
-{
-    /*
-     * TODO: the efficient way to do this is to modify FileMap to allow
-     * sub-regions of a file to be mapped.  A reference-counting scheme
-     * can manage the base memory mapping.  For now, we just create a brand
-     * new mapping off of the Zip archive file descriptor.
-     */
-
-    FileMap* newMap;
-    size_t compLen;
-    off64_t offset;
-
-    if (!getEntryInfo(entry, NULL, NULL, &compLen, &offset, NULL, NULL))
-        return NULL;
-
-    newMap = new FileMap();
-    if (!newMap->create(mFileName, mFd, offset, compLen, true)) {
-        newMap->release();
-        return NULL;
-    }
-
-    return newMap;
-}
-
-/*
- * Uncompress an entry, in its entirety, into the provided output buffer.
- *
- * This doesn't verify the data's CRC, which might be useful for
- * uncompressed data.  The caller should be able to manage it.
- */
-bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const
-{
-    const size_t kSequentialMin = 32768;
-    bool result = false;
-    int ent = entryToIndex(entry);
-    if (ent < 0)
-        return -1;
-
-    int method;
-    size_t uncompLen, compLen;
-    off64_t offset;
-    const unsigned char* ptr;
-
-    getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
-
-    FileMap* file = createEntryFileMap(entry);
-    if (file == NULL) {
-        goto bail;
-    }
-
-    ptr = (const unsigned char*) file->getDataPtr();
-
-    /*
-     * Experiment with madvise hint.  When we want to uncompress a file,
-     * we pull some stuff out of the central dir entry and then hit a
-     * bunch of compressed or uncompressed data sequentially.  The CDE
-     * visit will cause a limited amount of read-ahead because it's at
-     * the end of the file.  We could end up doing lots of extra disk
-     * access if the file we're prying open is small.  Bottom line is we
-     * probably don't want to turn MADV_SEQUENTIAL on and leave it on.
-     *
-     * So, if the compressed size of the file is above a certain minimum
-     * size, temporarily boost the read-ahead in the hope that the extra
-     * pair of system calls are negated by a reduction in page faults.
-     */
-    if (compLen > kSequentialMin)
-        file->advise(FileMap::SEQUENTIAL);
-
-    if (method == kCompressStored) {
-        memcpy(buffer, ptr, uncompLen);
-    } else {
-        if (!inflateBuffer(buffer, ptr, uncompLen, compLen))
-            goto unmap;
-    }
-
-    if (compLen > kSequentialMin)
-        file->advise(FileMap::NORMAL);
-
-    result = true;
-
-unmap:
-    file->release();
-bail:
-    return result;
-}
-
-/*
- * Uncompress an entry, in its entirety, to an open file descriptor.
- *
- * This doesn't verify the data's CRC, but probably should.
- */
-bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const
-{
-    bool result = false;
-    int ent = entryToIndex(entry);
-    if (ent < 0)
-        return -1;
-
-    int method;
-    size_t uncompLen, compLen;
-    off64_t offset;
-    const unsigned char* ptr;
-
-    getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
-
-    FileMap* file = createEntryFileMap(entry);
-    if (file == NULL) {
-        goto bail;
-    }
-
-    ptr = (const unsigned char*) file->getDataPtr();
-
-    if (method == kCompressStored) {
-        ssize_t actual = write(fd, ptr, uncompLen);
-        if (actual < 0) {
-            ALOGE("Write failed: %s\n", strerror(errno));
-            goto unmap;
-        } else if ((size_t) actual != uncompLen) {
-            ALOGE("Partial write during uncompress (" ZD " of " ZD ")\n",
-                (ZD_TYPE) actual, (ZD_TYPE) uncompLen);
-            goto unmap;
-        } else {
-            ALOGI("+++ successful write\n");
-        }
-    } else {
-        if (!inflateBuffer(fd, ptr, uncompLen, compLen))
-            goto unmap;
-    }
-
-    result = true;
-
-unmap:
-    file->release();
-bail:
-    return result;
-}
-
-/*
- * Uncompress "deflate" data from one buffer to another.
- */
-/*static*/ bool ZipFileRO::inflateBuffer(void* outBuf, const void* inBuf,
-    size_t uncompLen, size_t compLen)
-{
-    bool result = false;
-    z_stream zstream;
-    int zerr;
-
-    /*
-     * Initialize the zlib stream struct.
-     */
-    memset(&zstream, 0, sizeof(zstream));
-    zstream.zalloc = Z_NULL;
-    zstream.zfree = Z_NULL;
-    zstream.opaque = Z_NULL;
-    zstream.next_in = (Bytef*)inBuf;
-    zstream.avail_in = compLen;
-    zstream.next_out = (Bytef*) outBuf;
-    zstream.avail_out = uncompLen;
-    zstream.data_type = Z_UNKNOWN;
-
-    /*
-     * Use the undocumented "negative window bits" feature to tell zlib
-     * that there's no zlib header waiting for it.
-     */
-    zerr = inflateInit2(&zstream, -MAX_WBITS);
-    if (zerr != Z_OK) {
-        if (zerr == Z_VERSION_ERROR) {
-            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
-                ZLIB_VERSION);
-        } else {
-            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
-        }
-        goto bail;
-    }
-
-    /*
-     * Expand data.
-     */
-    zerr = inflate(&zstream, Z_FINISH);
-    if (zerr != Z_STREAM_END) {
-        ALOGW("Zip inflate failed, zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)\n",
-            zerr, zstream.next_in, zstream.avail_in,
-            zstream.next_out, zstream.avail_out);
-        goto z_bail;
-    }
-
-    /* paranoia */
-    if (zstream.total_out != uncompLen) {
-        ALOGW("Size mismatch on inflated file (%ld vs " ZD ")\n",
-            zstream.total_out, (ZD_TYPE) uncompLen);
-        goto z_bail;
-    }
-
-    result = true;
-
-z_bail:
-    inflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-    return result;
-}
-
-/*
- * Uncompress "deflate" data from one buffer to an open file descriptor.
- */
-/*static*/ bool ZipFileRO::inflateBuffer(int fd, const void* inBuf,
-    size_t uncompLen, size_t compLen)
-{
-    bool result = false;
-    const size_t kWriteBufSize = 32768;
-    unsigned char writeBuf[kWriteBufSize];
-    z_stream zstream;
-    int zerr;
-
-    /*
-     * Initialize the zlib stream struct.
-     */
-    memset(&zstream, 0, sizeof(zstream));
-    zstream.zalloc = Z_NULL;
-    zstream.zfree = Z_NULL;
-    zstream.opaque = Z_NULL;
-    zstream.next_in = (Bytef*)inBuf;
-    zstream.avail_in = compLen;
-    zstream.next_out = (Bytef*) writeBuf;
-    zstream.avail_out = sizeof(writeBuf);
-    zstream.data_type = Z_UNKNOWN;
-
-    /*
-     * Use the undocumented "negative window bits" feature to tell zlib
-     * that there's no zlib header waiting for it.
-     */
-    zerr = inflateInit2(&zstream, -MAX_WBITS);
-    if (zerr != Z_OK) {
-        if (zerr == Z_VERSION_ERROR) {
-            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
-                ZLIB_VERSION);
-        } else {
-            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
-        }
-        goto bail;
-    }
-
-    /*
-     * Loop while we have more to do.
-     */
-    do {
-        /*
-         * Expand data.
-         */
-        zerr = inflate(&zstream, Z_NO_FLUSH);
-        if (zerr != Z_OK && zerr != Z_STREAM_END) {
-            ALOGW("zlib inflate: zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)\n",
-                zerr, zstream.next_in, zstream.avail_in,
-                zstream.next_out, zstream.avail_out);
-            goto z_bail;
-        }
-
-        /* write when we're full or when we're done */
-        if (zstream.avail_out == 0 ||
-            (zerr == Z_STREAM_END && zstream.avail_out != sizeof(writeBuf)))
-        {
-            long writeSize = zstream.next_out - writeBuf;
-            int cc = write(fd, writeBuf, writeSize);
-            if (cc != (int) writeSize) {
-                ALOGW("write failed in inflate (%d vs %ld)\n", cc, writeSize);
-                goto z_bail;
-            }
-
-            zstream.next_out = writeBuf;
-            zstream.avail_out = sizeof(writeBuf);
-        }
-    } while (zerr == Z_OK);
-
-    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
-
-    /* paranoia */
-    if (zstream.total_out != uncompLen) {
-        ALOGW("Size mismatch on inflated file (%ld vs " ZD ")\n",
-            zstream.total_out, (ZD_TYPE) uncompLen);
-        goto z_bail;
-    }
-
-    result = true;
-
-z_bail:
-    inflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-    return result;
-}
diff --git a/libs/androidfw/ZipUtils.cpp b/libs/androidfw/ZipUtils.cpp
deleted file mode 100644
index db3479d..0000000
--- a/libs/androidfw/ZipUtils.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-//
-// Misc zip/gzip utility functions.
-//
-
-#define LOG_TAG "ziputil"
-
-#include <androidfw/ZipUtils.h>
-#include <androidfw/ZipFileRO.h>
-#include <utils/Log.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <zlib.h>
-
-using namespace android;
-
-/*
- * Utility function that expands zip/gzip "deflate" compressed data
- * into a buffer.
- *
- * "fd" is an open file positioned at the start of the "deflate" data
- * "buf" must hold at least "uncompressedLen" bytes.
- */
-/*static*/ bool ZipUtils::inflateToBuffer(int fd, void* buf,
-    long uncompressedLen, long compressedLen)
-{
-    bool result = false;
-	const unsigned long kReadBufSize = 32768;
-	unsigned char* readBuf = NULL;
-    z_stream zstream;
-    int zerr;
-    unsigned long compRemaining;
-
-    assert(uncompressedLen >= 0);
-    assert(compressedLen >= 0);
-
-	readBuf = new unsigned char[kReadBufSize];
-	if (readBuf == NULL)
-        goto bail;
-    compRemaining = compressedLen;
-
-    /*
-     * Initialize the zlib stream.
-     */
-	memset(&zstream, 0, sizeof(zstream));
-    zstream.zalloc = Z_NULL;
-    zstream.zfree = Z_NULL;
-    zstream.opaque = Z_NULL;
-    zstream.next_in = NULL;
-    zstream.avail_in = 0;
-    zstream.next_out = (Bytef*) buf;
-    zstream.avail_out = uncompressedLen;
-    zstream.data_type = Z_UNKNOWN;
-
-	/*
-	 * Use the undocumented "negative window bits" feature to tell zlib
-	 * that there's no zlib header waiting for it.
-	 */
-    zerr = inflateInit2(&zstream, -MAX_WBITS);
-    if (zerr != Z_OK) {
-        if (zerr == Z_VERSION_ERROR) {
-            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
-                ZLIB_VERSION);
-        } else {
-            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
-        }
-        goto bail;
-    }
-
-    /*
-     * Loop while we have data.
-     */
-    do {
-        unsigned long getSize;
-
-        /* read as much as we can */
-        if (zstream.avail_in == 0) {
-            getSize = (compRemaining > kReadBufSize) ?
-                        kReadBufSize : compRemaining;
-            ALOGV("+++ reading %ld bytes (%ld left)\n",
-                getSize, compRemaining);
-
-            int cc = read(fd, readBuf, getSize);
-            if (cc != (int) getSize) {
-                ALOGD("inflate read failed (%d vs %ld)\n",
-                    cc, getSize);
-                goto z_bail;
-            }
-
-            compRemaining -= getSize;
-
-            zstream.next_in = readBuf;
-            zstream.avail_in = getSize;
-        }
-
-        /* uncompress the data */
-        zerr = inflate(&zstream, Z_NO_FLUSH);
-        if (zerr != Z_OK && zerr != Z_STREAM_END) {
-            ALOGD("zlib inflate call failed (zerr=%d)\n", zerr);
-            goto z_bail;
-        }
-
-		/* output buffer holds all, so no need to write the output */
-    } while (zerr == Z_OK);
-
-    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
-
-    if ((long) zstream.total_out != uncompressedLen) {
-        ALOGW("Size mismatch on inflated file (%ld vs %ld)\n",
-            zstream.total_out, uncompressedLen);
-        goto z_bail;
-    }
-
-    // success!
-    result = true;
-
-z_bail:
-    inflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-	delete[] readBuf;
-    return result;
-}
-
-/*
- * Utility function that expands zip/gzip "deflate" compressed data
- * into a buffer.
- *
- * (This is a clone of the previous function, but it takes a FILE* instead
- * of an fd.  We could pass fileno(fd) to the above, but we can run into
- * trouble when "fp" has a different notion of what fd's file position is.)
- *
- * "fp" is an open file positioned at the start of the "deflate" data
- * "buf" must hold at least "uncompressedLen" bytes.
- */
-/*static*/ bool ZipUtils::inflateToBuffer(FILE* fp, void* buf,
-    long uncompressedLen, long compressedLen)
-{
-    bool result = false;
-	const unsigned long kReadBufSize = 32768;
-	unsigned char* readBuf = NULL;
-    z_stream zstream;
-    int zerr;
-    unsigned long compRemaining;
-
-    assert(uncompressedLen >= 0);
-    assert(compressedLen >= 0);
-
-	readBuf = new unsigned char[kReadBufSize];
-	if (readBuf == NULL)
-        goto bail;
-    compRemaining = compressedLen;
-
-    /*
-     * Initialize the zlib stream.
-     */
-	memset(&zstream, 0, sizeof(zstream));
-    zstream.zalloc = Z_NULL;
-    zstream.zfree = Z_NULL;
-    zstream.opaque = Z_NULL;
-    zstream.next_in = NULL;
-    zstream.avail_in = 0;
-    zstream.next_out = (Bytef*) buf;
-    zstream.avail_out = uncompressedLen;
-    zstream.data_type = Z_UNKNOWN;
-
-	/*
-	 * Use the undocumented "negative window bits" feature to tell zlib
-	 * that there's no zlib header waiting for it.
-	 */
-    zerr = inflateInit2(&zstream, -MAX_WBITS);
-    if (zerr != Z_OK) {
-        if (zerr == Z_VERSION_ERROR) {
-            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
-                ZLIB_VERSION);
-        } else {
-            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
-        }
-        goto bail;
-    }
-
-    /*
-     * Loop while we have data.
-     */
-    do {
-        unsigned long getSize;
-
-        /* read as much as we can */
-        if (zstream.avail_in == 0) {
-            getSize = (compRemaining > kReadBufSize) ?
-                        kReadBufSize : compRemaining;
-            ALOGV("+++ reading %ld bytes (%ld left)\n",
-                getSize, compRemaining);
-
-            int cc = fread(readBuf, 1, getSize, fp);
-            if (cc != (int) getSize) {
-                ALOGD("inflate read failed (%d vs %ld)\n",
-                    cc, getSize);
-                goto z_bail;
-            }
-
-            compRemaining -= getSize;
-
-            zstream.next_in = readBuf;
-            zstream.avail_in = getSize;
-        }
-
-        /* uncompress the data */
-        zerr = inflate(&zstream, Z_NO_FLUSH);
-        if (zerr != Z_OK && zerr != Z_STREAM_END) {
-            ALOGD("zlib inflate call failed (zerr=%d)\n", zerr);
-            goto z_bail;
-        }
-
-		/* output buffer holds all, so no need to write the output */
-    } while (zerr == Z_OK);
-
-    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
-
-    if ((long) zstream.total_out != uncompressedLen) {
-        ALOGW("Size mismatch on inflated file (%ld vs %ld)\n",
-            zstream.total_out, uncompressedLen);
-        goto z_bail;
-    }
-
-    // success!
-    result = true;
-
-z_bail:
-    inflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-	delete[] readBuf;
-    return result;
-}
-
-/*
- * Look at the contents of a gzip archive.  We want to know where the
- * data starts, and how long it will be after it is uncompressed.
- *
- * We expect to find the CRC and length as the last 8 bytes on the file.
- * This is a pretty reasonable thing to expect for locally-compressed
- * files, but there's a small chance that some extra padding got thrown
- * on (the man page talks about compressed data written to tape).  We
- * don't currently deal with that here.  If "gzip -l" whines, we're going
- * to fail too.
- *
- * On exit, "fp" is pointing at the start of the compressed data.
- */
-/*static*/ bool ZipUtils::examineGzip(FILE* fp, int* pCompressionMethod,
-    long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32)
-{
-    enum {  // flags
-        FTEXT       = 0x01,
-        FHCRC       = 0x02,
-        FEXTRA      = 0x04,
-        FNAME       = 0x08,
-        FCOMMENT    = 0x10,
-    };
-    int ic;
-    int method, flags;
-    int i;
-
-    ic = getc(fp);
-    if (ic != 0x1f || getc(fp) != 0x8b)
-        return false;       // not gzip
-    method = getc(fp);
-    flags = getc(fp);
-
-    /* quick sanity checks */
-    if (method == EOF || flags == EOF)
-        return false;
-    if (method != ZipFileRO::kCompressDeflated)
-        return false;
-
-    /* skip over 4 bytes of mod time, 1 byte XFL, 1 byte OS */
-    for (i = 0; i < 6; i++)
-        (void) getc(fp);
-    /* consume "extra" field, if present */
-    if ((flags & FEXTRA) != 0) {
-        int len;
-
-        len = getc(fp);
-        len |= getc(fp) << 8;
-        while (len-- && getc(fp) != EOF)
-            ;
-    }
-    /* consume filename, if present */
-    if ((flags & FNAME) != 0) {
-        do {
-            ic = getc(fp);
-        } while (ic != 0 && ic != EOF);
-    }
-    /* consume comment, if present */
-    if ((flags & FCOMMENT) != 0) {
-        do {
-            ic = getc(fp);
-        } while (ic != 0 && ic != EOF);
-    }
-    /* consume 16-bit header CRC, if present */
-    if ((flags & FHCRC) != 0) {
-        (void) getc(fp);
-        (void) getc(fp);
-    }
-
-    if (feof(fp) || ferror(fp))
-        return false;
-
-    /* seek to the end; CRC and length are in the last 8 bytes */
-    long curPosn = ftell(fp);
-    unsigned char buf[8];
-    fseek(fp, -8, SEEK_END);
-    *pCompressedLen = ftell(fp) - curPosn;
-
-    if (fread(buf, 1, 8, fp) != 8)
-        return false;
-    /* seek back to start of compressed data */
-    fseek(fp, curPosn, SEEK_SET);
-
-    *pCompressionMethod = method;
-    *pCRC32 = ZipFileRO::get4LE(&buf[0]);
-    *pUncompressedLen = ZipFileRO::get4LE(&buf[4]);
-
-    return true;
-}
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index d85009b..39009b8 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -7,8 +7,7 @@
     InputChannel_test.cpp \
     InputEvent_test.cpp \
     InputPublisherAndConsumer_test.cpp \
-    ObbFile_test.cpp \
-    ZipFileRO_test.cpp 
+    ObbFile_test.cpp
 
 shared_libraries := \
 	libandroidfw \
diff --git a/libs/androidfw/tests/ZipFileRO_test.cpp b/libs/androidfw/tests/ZipFileRO_test.cpp
deleted file mode 100644
index 344f974..0000000
--- a/libs/androidfw/tests/ZipFileRO_test.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "ZipFileRO_test"
-#include <androidfw/ZipFileRO.h>
-#include <utils/Log.h>
-
-#include <gtest/gtest.h>
-
-#include <fcntl.h>
-#include <string.h>
-
-namespace android {
-
-class ZipFileROTest : public testing::Test {
-protected:
-    virtual void SetUp() {
-    }
-
-    virtual void TearDown() {
-    }
-};
-
-TEST_F(ZipFileROTest, ZipTimeConvertSuccess) {
-    struct tm t;
-
-    // 2011-06-29 14:40:40
-    long when = 0x3EDD7514;
-
-    ZipFileRO::zipTimeToTimespec(when, &t);
-
-    EXPECT_EQ(2011, t.tm_year + 1900)
-            << "Year was improperly converted.";
-
-    EXPECT_EQ(6, t.tm_mon)
-            << "Month was improperly converted.";
-
-    EXPECT_EQ(29, t.tm_mday)
-            << "Day was improperly converted.";
-
-    EXPECT_EQ(14, t.tm_hour)
-            << "Hour was improperly converted.";
-
-    EXPECT_EQ(40, t.tm_min)
-            << "Minute was improperly converted.";
-
-    EXPECT_EQ(40, t.tm_sec)
-            << "Second was improperly converted.";
-}
-
-}
diff --git a/libs/rs/Allocation.cpp b/libs/rs/Allocation.cpp
index d69c55f..e37d5de 100644
--- a/libs/rs/Allocation.cpp
+++ b/libs/rs/Allocation.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2012 The Android Open Source Project
+ * 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.
@@ -51,17 +51,14 @@
                    RS_ALLOCATION_USAGE_GRAPHICS_VERTEX |
                    RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS |
                    RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET |
-                   RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
                    RS_ALLOCATION_USAGE_IO_INPUT |
                    RS_ALLOCATION_USAGE_IO_OUTPUT)) != 0) {
         ALOGE("Unknown usage specified.");
     }
 
-    if ((usage & (RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
-                  RS_ALLOCATION_USAGE_IO_INPUT)) != 0) {
+    if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) {
         mWriteAllowed = false;
-        if ((usage & ~(RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
-                       RS_ALLOCATION_USAGE_IO_INPUT |
+        if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT |
                        RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
                        RS_ALLOCATION_USAGE_SCRIPT)) != 0) {
             ALOGE("Invalid usage combination.");
diff --git a/libs/rs/driver/rsdAllocation.cpp b/libs/rs/driver/rsdAllocation.cpp
index fb93d82..f358f93 100644
--- a/libs/rs/driver/rsdAllocation.cpp
+++ b/libs/rs/driver/rsdAllocation.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-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.
@@ -27,6 +27,7 @@
 #include "hardware/gralloc.h"
 #include "ui/Rect.h"
 #include "ui/GraphicBufferMapper.h"
+#include "gui/SurfaceTexture.h"
 
 #include <GLES/gl.h>
 #include <GLES2/gl2.h>
@@ -139,7 +140,7 @@
 static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
 
-    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE) {
+    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
         if (!drv->textureID) {
             RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
         }
@@ -475,7 +476,8 @@
 }
 
 void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) {
-    ALOGE("not implemented");
+    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+    alloc->mHal.state.surfaceTexture->updateTexImage();
 }
 
 
diff --git a/libs/rs/driver/rsdCore.cpp b/libs/rs/driver/rsdCore.cpp
index 35a5c08..6a532e9 100644
--- a/libs/rs/driver/rsdCore.cpp
+++ b/libs/rs/driver/rsdCore.cpp
@@ -227,13 +227,13 @@
 
 
     int cpu = sysconf(_SC_NPROCESSORS_ONLN);
-    ALOGV("%p Launching thread(s), CPUs %i", rsc, cpu);
     if(rsc->props.mDebugMaxThreads && (cpu > (int)rsc->props.mDebugMaxThreads)) {
         cpu = rsc->props.mDebugMaxThreads;
     }
     if (cpu < 2) {
         cpu = 0;
     }
+    ALOGV("%p Launching thread(s), CPUs %i", rsc, cpu);
 
     dc->mWorkers.mCount = (uint32_t)cpu;
     dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
diff --git a/libs/rs/driver/rsdProgram.cpp b/libs/rs/driver/rsdProgram.cpp
index fa4cb0f..30a4c5f 100644
--- a/libs/rs/driver/rsdProgram.cpp
+++ b/libs/rs/driver/rsdProgram.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-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.
@@ -41,7 +41,7 @@
                                    textureNames, textureNamesCount, textureNamesLength);
     pv->mHal.drv = drv;
 
-    return drv->createShader();
+    return true;
 }
 
 static void SyncProgramConstants(const Context *rsc, const Program *p) {
@@ -88,7 +88,7 @@
                                    textureNames, textureNamesCount, textureNamesLength);
     pf->mHal.drv = drv;
 
-    return drv->createShader();
+    return true;
 }
 
 void rsdProgramFragmentSetActive(const Context *rsc, const ProgramFragment *pf) {
diff --git a/libs/rs/driver/rsdShader.cpp b/libs/rs/driver/rsdShader.cpp
index 1e73b95..a386735 100644
--- a/libs/rs/driver/rsdShader.cpp
+++ b/libs/rs/driver/rsdShader.cpp
@@ -39,7 +39,10 @@
     initMemberVars();
     initAttribAndUniformArray();
     init(textureNames, textureNamesCount, textureNamesLength);
-    createTexturesString(textureNames, textureNamesCount, textureNamesLength);
+
+    for(size_t i=0; i < textureNamesCount; i++) {
+        mTextureNames.push(String8(textureNames[i], textureNamesLength[i]));
+    }
 }
 
 RsdShader::~RsdShader() {
@@ -138,37 +141,42 @@
     }
 }
 
-void RsdShader::createTexturesString(const char** textureNames, size_t textureNamesCount,
-                                     const size_t *textureNamesLength) {
-    mShaderTextures.setTo("");
+void RsdShader::appendTextures() {
+
+    // TODO: this does not yet handle cases where the texture changes between IO
+    // input and local
+    bool appendUsing = true;
     for (uint32_t ct = 0; ct < mRSProgram->mHal.state.texturesCount; ct ++) {
         if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) {
             Allocation *a = mRSProgram->mHal.state.textures[ct];
             if (a && a->mHal.state.surfaceTextureID) {
-                mShaderTextures.append("uniform samplerExternalOES UNI_");
+                if(appendUsing) {
+                    mShader.append("#extension GL_OES_EGL_image_external : require\n");
+                    appendUsing = false;
+                }
+                mShader.append("uniform samplerExternalOES UNI_");
+                mTextureTargets[ct] = GL_TEXTURE_EXTERNAL_OES;
             } else {
-                mShaderTextures.append("uniform sampler2D UNI_");
+                mShader.append("uniform sampler2D UNI_");
+                mTextureTargets[ct] = GL_TEXTURE_2D;
             }
-            mTextureTargets[ct] = GL_TEXTURE_2D;
         } else {
-            mShaderTextures.append("uniform samplerCube UNI_");
+            mShader.append("uniform samplerCube UNI_");
             mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP;
         }
 
-        mShaderTextures.append(textureNames[ct], textureNamesLength[ct]);
-        mShaderTextures.append(";\n");
+        mShader.append(mTextureNames[ct]);
+        mShader.append(";\n");
     }
 }
 
 bool RsdShader::createShader() {
-
     if (mType == GL_FRAGMENT_SHADER) {
         mShader.append("precision mediump float;\n");
     }
     appendUserConstants();
     appendAttributes();
-    mShader.append(mShaderTextures);
-
+    appendTextures();
     mShader.append(mUserShader);
 
     return true;
@@ -178,6 +186,10 @@
     mShaderID = glCreateShader(mType);
     rsAssert(mShaderID);
 
+    if(!mShader.length()) {
+        createShader();
+    }
+
     if (rsc->props.mLogShaders) {
         ALOGV("Loading shader type %x, ID %i", mType, mShaderID);
         ALOGV("%s", mShader.string());
@@ -423,7 +435,9 @@
         }
 
         DrvAllocation *drvTex = (DrvAllocation *)mRSProgram->mHal.state.textures[ct]->mHal.drv;
-        if (drvTex->glTarget != GL_TEXTURE_2D && drvTex->glTarget != GL_TEXTURE_CUBE_MAP) {
+        if (drvTex->glTarget != GL_TEXTURE_2D &&
+            drvTex->glTarget != GL_TEXTURE_CUBE_MAP &&
+            drvTex->glTarget != GL_TEXTURE_EXTERNAL_OES) {
             ALOGE("Attempting to bind unknown texture to shader id %u, texture unit %u",
                   (uint)this, ct);
             rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
diff --git a/libs/rs/driver/rsdShader.h b/libs/rs/driver/rsdShader.h
index e32145f..6c0b616 100644
--- a/libs/rs/driver/rsdShader.h
+++ b/libs/rs/driver/rsdShader.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-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.
@@ -81,15 +81,12 @@
 
     void appendAttributes();
     void appendTextures();
-    void createTexturesString(const char** textureNames, size_t textureNamesCount,
-                              const size_t *textureNamesLength);
 
     void initAttribAndUniformArray();
 
     mutable bool mDirty;
     android::String8 mShader;
     android::String8 mUserShader;
-    android::String8 mShaderTextures;
     uint32_t mShaderID;
     uint32_t mType;
 
@@ -101,6 +98,8 @@
     android::String8 *mUniformNames;
     uint32_t *mUniformArraySizes;
 
+    android::Vector<android::String8> mTextureNames;
+
     int32_t mTextureUniformIndexStart;
 
     void logUniform(const android::renderscript::Element *field,
diff --git a/libs/rs/driver/rsdShaderCache.cpp b/libs/rs/driver/rsdShaderCache.cpp
index 89d3c45..50cb9f9 100644
--- a/libs/rs/driver/rsdShaderCache.cpp
+++ b/libs/rs/driver/rsdShaderCache.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-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.
@@ -119,7 +119,6 @@
     if (!vtx->getShaderID() || !frag->getShaderID()) {
         return false;
     }
-    //ALOGV("rsdShaderCache lookup  vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID());
     uint32_t entryCount = mEntries.size();
     for (uint32_t ct = 0; ct < entryCount; ct ++) {
         if ((mEntries[ct]->vtx == vtx->getShaderID()) &&
@@ -134,8 +133,6 @@
         }
     }
 
-    //ALOGV("RsdShaderCache miss");
-    //ALOGE("e0 %x", glGetError());
     ProgramEntry *e = new ProgramEntry(vtx->getAttribCount(),
                                        vtx->getUniformCount(),
                                        frag->getUniformCount());
diff --git a/libs/rs/driver/rsdShaderCache.h b/libs/rs/driver/rsdShaderCache.h
index 0beecae..1192916 100644
--- a/libs/rs/driver/rsdShaderCache.h
+++ b/libs/rs/driver/rsdShaderCache.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-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.
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index cf4a391..b373056 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -69,6 +69,12 @@
     ret int32_t
 }
 
+AllocationGetSurfaceTextureID2 {
+    param RsAllocation alloc
+    param void *st
+    sync
+}
+
 AllocationSetSurface {
     param RsAllocation alloc
     param RsNativeWindow sur
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index a404c49..cdff49c 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -20,6 +20,7 @@
 #include "rs_hal.h"
 
 #include "system/window.h"
+#include "gui/SurfaceTexture.h"
 
 using namespace android;
 using namespace android::renderscript;
@@ -64,6 +65,7 @@
 
 Allocation::~Allocation() {
     freeChildrenUnlocked();
+    setSurfaceTexture(mRSC, NULL);
     mRSC->mHal.funcs.allocation.destroy(mRSC, this);
 }
 
@@ -424,6 +426,18 @@
     return id;
 }
 
+void Allocation::setSurfaceTexture(const Context *rsc, SurfaceTexture *st) {
+    if(st != mHal.state.surfaceTexture) {
+        if(mHal.state.surfaceTexture != NULL) {
+            mHal.state.surfaceTexture->decStrong(NULL);
+        }
+        mHal.state.surfaceTexture = st;
+        if(mHal.state.surfaceTexture != NULL) {
+            mHal.state.surfaceTexture->incStrong(NULL);
+        }
+    }
+}
+
 void Allocation::setSurface(const Context *rsc, RsNativeWindow sur) {
     ANativeWindow *nw = (ANativeWindow *)sur;
     ANativeWindow *old = mHal.state.wndSurface;
@@ -696,6 +710,11 @@
     return alloc->getSurfaceTextureID(rsc);
 }
 
+void rsi_AllocationGetSurfaceTextureID2(Context *rsc, RsAllocation valloc, void *vst, size_t len) {
+    Allocation *alloc = static_cast<Allocation *>(valloc);
+    alloc->setSurfaceTexture(rsc, static_cast<SurfaceTexture *>(vst));
+}
+
 void rsi_AllocationSetSurface(Context *rsc, RsAllocation valloc, RsNativeWindow sur) {
     Allocation *alloc = static_cast<Allocation *>(valloc);
     alloc->setSurface(rsc, sur);
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index 58a6fca..e2783d2 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -23,6 +23,8 @@
 
 // ---------------------------------------------------------------------------
 namespace android {
+class SurfaceTexture;
+
 namespace renderscript {
 
 class Program;
@@ -60,6 +62,7 @@
             void * usrPtr;
             int32_t surfaceTextureID;
             ANativeWindow *wndSurface;
+            SurfaceTexture *surfaceTexture;
         };
         State state;
 
@@ -130,6 +133,7 @@
     }
 
     int32_t getSurfaceTextureID(const Context *rsc);
+    void setSurfaceTexture(const Context *rsc, SurfaceTexture *st);
     void setSurface(const Context *rsc, RsNativeWindow sur);
     void ioSend(const Context *rsc);
     void ioReceive(const Context *rsc);
diff --git a/libs/rs/rsDefines.h b/libs/rs/rsDefines.h
index 990ef26..0e0cd8d 100644
--- a/libs/rs/rsDefines.h
+++ b/libs/rs/rsDefines.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2007-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.
@@ -100,9 +100,8 @@
     RS_ALLOCATION_USAGE_GRAPHICS_VERTEX = 0x0004,
     RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS = 0x0008,
     RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET = 0x0010,
-    RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE = 0x0020,
-    RS_ALLOCATION_USAGE_IO_INPUT = 0x0040,
-    RS_ALLOCATION_USAGE_IO_OUTPUT = 0x0080,
+    RS_ALLOCATION_USAGE_IO_INPUT = 0x0020,
+    RS_ALLOCATION_USAGE_IO_OUTPUT = 0x0040,
 
     RS_ALLOCATION_USAGE_ALL = 0x00FF
 };
diff --git a/libs/rs/scriptc/rs_allocation.rsh b/libs/rs/scriptc/rs_allocation.rsh
index 392a3ef..b0840a0 100644
--- a/libs/rs/scriptc/rs_allocation.rsh
+++ b/libs/rs/scriptc/rs_allocation.rsh
@@ -14,31 +14,6 @@
  * limitations under the License.
  */
 
-/*! \mainpage notitle
- *
- * Renderscript is a high-performance runtime that provides graphics rendering and
- * compute operations at the native level. Renderscript code is compiled on devices
- * at runtime to allow platform-independence as well.
- * This reference documentation describes the Renderscript runtime APIs, which you
- * can utilize to write Renderscript code in C99. The Renderscript header
- * files are automatically included for you, except for the rs_graphics.rsh header. If
- * you are doing graphics rendering, include the graphics header file like this:
- *
- * <code>#include "rs_graphics.rsh"</code>
- *
- * To use Renderscript, you need to utilize the Renderscript runtime APIs documented here
- * as well as the Android framework APIs for Renderscript.
- * For documentation on the Android framework APIs, see the <a target="_parent" href=
- * "http://developer.android.com/reference/android/renderscript/package-summary.html">
- * android.renderscript</a> package reference.
- * For more information on how to develop with Renderscript and how the runtime and
- * Android framework APIs interact, see the <a target="_parent" href=
- * "http://developer.android.com/guide/topics/renderscript/index.html">Renderscript
- * developer guide</a> and the <a target="_parent" href=
- * "http://developer.android.com/resources/samples/RenderScript/index.html">
- * Renderscript samples</a>.
- */
-
 /** @file rs_allocation.rsh
  *  \brief Allocation routines
  *
@@ -168,6 +143,8 @@
 extern const void * __attribute__((overloadable))
     rsGetElementAt(rs_allocation, uint32_t x, uint32_t y, uint32_t z);
 
+#if (defined(RS_VERSION) && (RS_VERSION >= 16))
+
 /**
  * @param a allocation to get data from
  * @return element describing allocation layout
@@ -216,26 +193,7 @@
 extern const float4 __attribute__((overloadable))
     rsSample(rs_allocation a, rs_sampler s, float2 location, float lod);
 
-/**
- * Fetch allocation in a way described by the sampler
- * @param a 3D allocation to sample from
- * @param s sampler state
- * @param location to sample from
- */
-extern const float4 __attribute__((overloadable))
-    rsSample(rs_allocation a, rs_sampler s, float3 location);
-
-/**
- * Fetch allocation in a way described by the sampler
- * @param a 3D allocation to sample from
- * @param s sampler state
- * @param location to sample from
- * @param lod mip level to sample from, for fractional values
- *            mip levels will be interpolated if
- *            RS_SAMPLER_LINEAR_MIP_LINEAR is used
- */
-extern const float4 __attribute__((overloadable))
-    rsSample(rs_allocation a, rs_sampler s, float3 location, float lod);
+#endif // (defined(RS_VERSION) && (RS_VERSION >= 16))
 
 #endif
 
diff --git a/libs/rs/scriptc/rs_core.rsh b/libs/rs/scriptc/rs_core.rsh
index 5b99976..1b0f9db 100644
--- a/libs/rs/scriptc/rs_core.rsh
+++ b/libs/rs/scriptc/rs_core.rsh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-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.
@@ -14,6 +14,31 @@
  * limitations under the License.
  */
 
+ /*! \mainpage notitle
+  *
+  * Renderscript is a high-performance runtime that provides graphics rendering and
+  * compute operations at the native level. Renderscript code is compiled on devices
+  * at runtime to allow platform-independence as well.
+  * This reference documentation describes the Renderscript runtime APIs, which you
+  * can utilize to write Renderscript code in C99. The Renderscript header
+  * files are automatically included for you, except for the rs_graphics.rsh header. If
+  * you are doing graphics rendering, include the graphics header file like this:
+  *
+  * <code>#include "rs_graphics.rsh"</code>
+  *
+  * To use Renderscript, you need to utilize the Renderscript runtime APIs documented here
+  * as well as the Android framework APIs for Renderscript.
+  * For documentation on the Android framework APIs, see the <a target="_parent" href=
+  * "http://developer.android.com/reference/android/renderscript/package-summary.html">
+  * android.renderscript</a> package reference.
+  * For more information on how to develop with Renderscript and how the runtime and
+  * Android framework APIs interact, see the <a target="_parent" href=
+  * "http://developer.android.com/guide/topics/renderscript/index.html">Renderscript
+  * developer guide</a> and the <a target="_parent" href=
+  * "http://developer.android.com/resources/samples/RenderScript/index.html">
+  * Renderscript samples</a>.
+  */
+
 /** @file rs_core.rsh
  *  \brief todo-jsams
  *
@@ -33,16 +58,12 @@
 #include "rs_debug.rsh"
 #include "rs_element.rsh"
 #include "rs_math.rsh"
-#include "rs_mesh.rsh"
 #include "rs_matrix.rsh"
 #include "rs_object.rsh"
-#include "rs_program.rsh"
 #include "rs_quaternion.rsh"
 #include "rs_sampler.rsh"
 #include "rs_time.rsh"
 
-
-
 /**
  * Send a message back to the client.  Will not block and returns true
  * if the message was sendable and false if the fifo was full.
diff --git a/libs/rs/scriptc/rs_element.rsh b/libs/rs/scriptc/rs_element.rsh
index 72cb51c..1a4cdb75 100644
--- a/libs/rs/scriptc/rs_element.rsh
+++ b/libs/rs/scriptc/rs_element.rsh
@@ -14,31 +14,6 @@
  * limitations under the License.
  */
 
-/*! \mainpage notitle
- *
- * Renderscript is a high-performance runtime that provides graphics rendering and
- * compute operations at the native level. Renderscript code is compiled on devices
- * at runtime to allow platform-independence as well.
- * This reference documentation describes the Renderscript runtime APIs, which you
- * can utilize to write Renderscript code in C99. The Renderscript header
- * files are automatically included for you, except for the rs_graphics.rsh header. If
- * you are doing graphics rendering, include the graphics header file like this:
- *
- * <code>#include "rs_graphics.rsh"</code>
- *
- * To use Renderscript, you need to utilize the Renderscript runtime APIs documented here
- * as well as the Android framework APIs for Renderscript.
- * For documentation on the Android framework APIs, see the <a target="_parent" href=
- * "http://developer.android.com/reference/android/renderscript/package-summary.html">
- * android.renderscript</a> package reference.
- * For more information on how to develop with Renderscript and how the runtime and
- * Android framework APIs interact, see the <a target="_parent" href=
- * "http://developer.android.com/guide/topics/renderscript/index.html">Renderscript
- * developer guide</a> and the <a target="_parent" href=
- * "http://developer.android.com/resources/samples/RenderScript/index.html">
- * Renderscript samples</a>.
- */
-
 /** @file rs_element.rsh
  *  \brief Element routines
  *
@@ -48,6 +23,8 @@
 #ifndef __RS_ELEMENT_RSH__
 #define __RS_ELEMENT_RSH__
 
+#if (defined(RS_VERSION) && (RS_VERSION >= 16))
+
 /**
  * @param e element to get data from
  * @return number of sub-elements in this element
@@ -130,5 +107,7 @@
 extern uint32_t __attribute__((overloadable))
     rsElementGetVectorSize(rs_element e);
 
+#endif // (defined(RS_VERSION) && (RS_VERSION >= 16))
+
 #endif // __RS_ELEMENT_RSH__
 
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index 80491ee..44ee99f 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-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.
@@ -23,6 +23,9 @@
 #ifndef __RS_GRAPHICS_RSH__
 #define __RS_GRAPHICS_RSH__
 
+#include "rs_mesh.rsh"
+#include "rs_program.rsh"
+
 #if (defined(RS_VERSION) && (RS_VERSION >= 14))
 /**
  * Set the color target used for all subsequent rendering calls
diff --git a/libs/rs/scriptc/rs_mesh.rsh b/libs/rs/scriptc/rs_mesh.rsh
index 88f229b..87ffd33 100644
--- a/libs/rs/scriptc/rs_mesh.rsh
+++ b/libs/rs/scriptc/rs_mesh.rsh
@@ -14,31 +14,6 @@
  * limitations under the License.
  */
 
-/*! \mainpage notitle
- *
- * Renderscript is a high-performance runtime that provides graphics rendering and
- * compute operations at the native level. Renderscript code is compiled on devices
- * at runtime to allow platform-independence as well.
- * This reference documentation describes the Renderscript runtime APIs, which you
- * can utilize to write Renderscript code in C99. The Renderscript header
- * files are automatically included for you, except for the rs_graphics.rsh header. If
- * you are doing graphics rendering, include the graphics header file like this:
- *
- * <code>#include "rs_graphics.rsh"</code>
- *
- * To use Renderscript, you need to utilize the Renderscript runtime APIs documented here
- * as well as the Android framework APIs for Renderscript.
- * For documentation on the Android framework APIs, see the <a target="_parent" href=
- * "http://developer.android.com/reference/android/renderscript/package-summary.html">
- * android.renderscript</a> package reference.
- * For more information on how to develop with Renderscript and how the runtime and
- * Android framework APIs interact, see the <a target="_parent" href=
- * "http://developer.android.com/guide/topics/renderscript/index.html">Renderscript
- * developer guide</a> and the <a target="_parent" href=
- * "http://developer.android.com/resources/samples/RenderScript/index.html">
- * Renderscript samples</a>.
- */
-
 /** @file rs_mesh.rsh
  *  \brief Mesh routines
  *
@@ -48,13 +23,15 @@
 #ifndef __RS_MESH_RSH__
 #define __RS_MESH_RSH__
 
+#if (defined(RS_VERSION) && (RS_VERSION >= 16))
+
 /**
  * @param m mesh to get data from
  * @return number of allocations in the mesh that contain vertex
  *         data
  */
 extern uint32_t __attribute__((overloadable))
-    rsMeshGetVertexAllocationCount(rs_mesh m);
+    rsgMeshGetVertexAllocationCount(rs_mesh m);
 
 /**
  * @param m mesh to get data from
@@ -63,7 +40,7 @@
  *         containing index data
  */
 extern uint32_t __attribute__((overloadable))
-    rsMeshGetPrimitiveCount(rs_mesh m);
+    rsgMeshGetPrimitiveCount(rs_mesh m);
 
 /**
  * @param m mesh to get data from
@@ -71,7 +48,7 @@
  * @return allocation containing vertex data
  */
 extern rs_allocation __attribute__((overloadable))
-    rsMeshGetVertexAllocation(rs_mesh m, uint32_t index);
+    rsgMeshGetVertexAllocation(rs_mesh m, uint32_t index);
 
 /**
  * @param m mesh to get data from
@@ -79,7 +56,7 @@
  * @return allocation containing index data
  */
 extern rs_allocation __attribute__((overloadable))
-    rsMeshGetIndexAllocation(rs_mesh m, uint32_t index);
+    rsgMeshGetIndexAllocation(rs_mesh m, uint32_t index);
 
 /**
  * @param m mesh to get data from
@@ -87,7 +64,9 @@
  * @return primitive describing how the mesh is rendered
  */
 extern rs_primitive __attribute__((overloadable))
-    rsMeshGetPrimitive(rs_mesh m, uint32_t index);
+    rsgMeshGetPrimitive(rs_mesh m, uint32_t index);
+
+#endif // (defined(RS_VERSION) && (RS_VERSION >= 16))
 
 #endif // __RS_MESH_RSH__
 
diff --git a/libs/rs/scriptc/rs_program.rsh b/libs/rs/scriptc/rs_program.rsh
index 8c52680..6a9929e 100644
--- a/libs/rs/scriptc/rs_program.rsh
+++ b/libs/rs/scriptc/rs_program.rsh
@@ -14,31 +14,6 @@
  * limitations under the License.
  */
 
-/*! \mainpage notitle
- *
- * Renderscript is a high-performance runtime that provides graphics rendering and
- * compute operations at the native level. Renderscript code is compiled on devices
- * at runtime to allow platform-independence as well.
- * This reference documentation describes the Renderscript runtime APIs, which you
- * can utilize to write Renderscript code in C99. The Renderscript header
- * files are automatically included for you, except for the rs_graphics.rsh header. If
- * you are doing graphics rendering, include the graphics header file like this:
- *
- * <code>#include "rs_graphics.rsh"</code>
- *
- * To use Renderscript, you need to utilize the Renderscript runtime APIs documented here
- * as well as the Android framework APIs for Renderscript.
- * For documentation on the Android framework APIs, see the <a target="_parent" href=
- * "http://developer.android.com/reference/android/renderscript/package-summary.html">
- * android.renderscript</a> package reference.
- * For more information on how to develop with Renderscript and how the runtime and
- * Android framework APIs interact, see the <a target="_parent" href=
- * "http://developer.android.com/guide/topics/renderscript/index.html">Renderscript
- * developer guide</a> and the <a target="_parent" href=
- * "http://developer.android.com/resources/samples/RenderScript/index.html">
- * Renderscript samples</a>.
- */
-
 /** @file rs_program.rsh
  *  \brief Program object routines
  *
@@ -48,6 +23,8 @@
 #ifndef __RS_PROGRAM_RSH__
 #define __RS_PROGRAM_RSH__
 
+#if (defined(RS_VERSION) && (RS_VERSION >= 16))
+
 /**
  * @hide
  * Get program store depth function
@@ -55,7 +32,7 @@
  * @param ps
  */
 extern rs_depth_func __attribute__((overloadable))
-    rsProgramStoreGetDepthFunc(rs_program_store ps);
+    rsgProgramStoreGetDepthFunc(rs_program_store ps);
 
 /**
  * @hide
@@ -64,7 +41,7 @@
  * @param ps
  */
 extern bool __attribute__((overloadable))
-    rsProgramStoreGetDepthMask(rs_program_store ps);
+    rsgProgramStoreGetDepthMask(rs_program_store ps);
 /**
  * @hide
  * Get program store red component color mask
@@ -72,7 +49,7 @@
  * @param ps
  */
 extern bool __attribute__((overloadable))
-    rsProgramStoreGetColorMaskR(rs_program_store ps);
+    rsgProgramStoreGetColorMaskR(rs_program_store ps);
 
 /**
  * @hide
@@ -81,7 +58,7 @@
  * @param ps
  */
 extern bool __attribute__((overloadable))
-    rsProgramStoreGetColorMaskG(rs_program_store ps);
+    rsgProgramStoreGetColorMaskG(rs_program_store ps);
 
 /**
  * @hide
@@ -90,7 +67,7 @@
  * @param ps
  */
 extern bool __attribute__((overloadable))
-    rsProgramStoreGetColorMaskB(rs_program_store ps);
+    rsgProgramStoreGetColorMaskB(rs_program_store ps);
 
 /**
  * @hide
@@ -99,7 +76,7 @@
  * @param ps
  */
 extern bool __attribute__((overloadable))
-    rsProgramStoreGetColorMaskA(rs_program_store ps);
+    rsgProgramStoreGetColorMaskA(rs_program_store ps);
 
 /**
  * @hide
@@ -108,7 +85,7 @@
  * @param ps
  */
 extern rs_blend_src_func __attribute__((overloadable))
-        rsProgramStoreGetBlendSrcFunc(rs_program_store ps);
+        rsgProgramStoreGetBlendSrcFunc(rs_program_store ps);
 
 /**
  * @hide
@@ -117,7 +94,7 @@
  * @param ps
  */
 extern rs_blend_dst_func __attribute__((overloadable))
-    rsProgramStoreGetBlendDstFunc(rs_program_store ps);
+    rsgProgramStoreGetBlendDstFunc(rs_program_store ps);
 
 /**
  * @hide
@@ -126,7 +103,7 @@
  * @param ps
  */
 extern bool __attribute__((overloadable))
-    rsProgramStoreGetDitherEnabled(rs_program_store ps);
+    rsgProgramStoreGetDitherEnabled(rs_program_store ps);
 
 /**
  * @hide
@@ -135,7 +112,7 @@
  * @param pr
  */
 extern bool __attribute__((overloadable))
-    rsProgramRasterGetPointSpriteEnabled(rs_program_raster pr);
+    rsgProgramRasterGetPointSpriteEnabled(rs_program_raster pr);
 
 /**
  * @hide
@@ -144,9 +121,9 @@
  * @param pr
  */
 extern rs_cull_mode __attribute__((overloadable))
-    rsProgramRasterGetCullMode(rs_program_raster pr);
+    rsgProgramRasterGetCullMode(rs_program_raster pr);
 
-
+#endif // (defined(RS_VERSION) && (RS_VERSION >= 16))
 
 #endif // __RS_PROGRAM_RSH__
 
diff --git a/libs/rs/scriptc/rs_sampler.rsh b/libs/rs/scriptc/rs_sampler.rsh
index 130eca0..c8948c7 100644
--- a/libs/rs/scriptc/rs_sampler.rsh
+++ b/libs/rs/scriptc/rs_sampler.rsh
@@ -14,31 +14,6 @@
  * limitations under the License.
  */
 
-/*! \mainpage notitle
- *
- * Renderscript is a high-performance runtime that provides graphics rendering and
- * compute operations at the native level. Renderscript code is compiled on devices
- * at runtime to allow platform-independence as well.
- * This reference documentation describes the Renderscript runtime APIs, which you
- * can utilize to write Renderscript code in C99. The Renderscript header
- * files are automatically included for you, except for the rs_graphics.rsh header. If
- * you are doing graphics rendering, include the graphics header file like this:
- *
- * <code>#include "rs_graphics.rsh"</code>
- *
- * To use Renderscript, you need to utilize the Renderscript runtime APIs documented here
- * as well as the Android framework APIs for Renderscript.
- * For documentation on the Android framework APIs, see the <a target="_parent" href=
- * "http://developer.android.com/reference/android/renderscript/package-summary.html">
- * android.renderscript</a> package reference.
- * For more information on how to develop with Renderscript and how the runtime and
- * Android framework APIs interact, see the <a target="_parent" href=
- * "http://developer.android.com/guide/topics/renderscript/index.html">Renderscript
- * developer guide</a> and the <a target="_parent" href=
- * "http://developer.android.com/resources/samples/RenderScript/index.html">
- * Renderscript samples</a>.
- */
-
 /** @file rs_sampler.rsh
  *  \brief Sampler routines
  *
@@ -48,6 +23,8 @@
 #ifndef __RS_SAMPLER_RSH__
 #define __RS_SAMPLER_RSH__
 
+#if (defined(RS_VERSION) && (RS_VERSION >= 16))
+
 /**
  * @hide
  * Get sampler minification value
@@ -93,5 +70,7 @@
 extern float __attribute__((overloadable))
     rsSamplerGetAnisotropy(rs_sampler s);
 
+#endif // (defined(RS_VERSION) && (RS_VERSION >= 16))
+
 #endif // __RS_SAMPLER_RSH__
 
diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh
index f8c2657..10617d8 100644
--- a/libs/rs/scriptc/rs_types.rsh
+++ b/libs/rs/scriptc/rs_types.rsh
@@ -402,6 +402,8 @@
 
 #endif //defined(RS_VERSION) && (RS_VERSION >= 14)
 
+#if (defined(RS_VERSION) && (RS_VERSION >= 16))
+
 /**
  * Describes the way mesh vertex data is interpreted when rendering
  *
@@ -552,4 +554,6 @@
     RS_SAMPLER_INVALID              = 100,
 } rs_sampler_value;
 
-#endif
+#endif // (defined(RS_VERSION) && (RS_VERSION >= 16))
+
+#endif // __RS_TYPES_RSH__
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 9748d3b..82dd308 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -608,16 +608,15 @@
      * Adjusts the master volume for the device's audio amplifier.
      * <p>
      *
-     * @param direction The direction to adjust the volume. One of
-     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
-     *            {@link #ADJUST_SAME}.
+     * @param steps The number of volume steps to adjust. A positive
+     *            value will raise the volume.
      * @param flags One or more flags.
      * @hide
      */
-    public void adjustMasterVolume(int direction, int flags) {
+    public void adjustMasterVolume(int steps, int flags) {
         IAudioService service = getService();
         try {
-            service.adjustMasterVolume(direction, flags);
+            service.adjustMasterVolume(steps, flags);
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in adjustMasterVolume", e);
         }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index aa60d0a..5f6a61d 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -159,6 +159,9 @@
     // but to support integer based AudioManager API we translate it to 0 - 100
     private static final int MAX_MASTER_VOLUME = 100;
 
+    // Maximum volume adjust steps allowed in a single batch call.
+    private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4;
+
     /* Sound effect file names  */
     private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
     private static final String[] SOUND_EFFECT_FILES = new String[] {
@@ -619,29 +622,19 @@
     }
 
     /** @see AudioManager#adjustMasterVolume(int) */
-    public void adjustMasterVolume(int direction, int flags) {
-        ensureValidDirection(direction);
+    public void adjustMasterVolume(int steps, int flags) {
+        ensureValidSteps(steps);
         int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
         int delta = 0;
-        for (int i = 0; i < mMasterVolumeRamp.length; i += 2) {
-            int testVolume = mMasterVolumeRamp[i];
-            int testDelta =  mMasterVolumeRamp[i + 1];
-            if (direction == AudioManager.ADJUST_RAISE) {
-                if (volume >= testVolume) {
-                    delta = testDelta;
-                } else {
-                    break;
-                }
-            } else if (direction == AudioManager.ADJUST_LOWER) {
-                if (volume - testDelta >= testVolume) {
-                    delta = -testDelta;
-                } else {
-                    break;
-                }
-            }
+        int numSteps = Math.abs(steps);
+        int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
+        for (int i = 0; i < numSteps; ++i) {
+            delta = findVolumeDelta(direction, volume);
+            volume += delta;
         }
-//        Log.d(TAG, "adjustMasterVolume volume: " + volume + " delta: " + delta + " direction: " + direction);
-        setMasterVolume(volume + delta, flags);
+
+        //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps);
+        setMasterVolume(volume, flags);
     }
 
     /** @see AudioManager#setStreamVolume(int, int, int) */
@@ -682,6 +675,41 @@
         sendVolumeUpdate(streamType, oldIndex, index, flags);
     }
 
+    private int findVolumeDelta(int direction, int volume) {
+        int delta = 0;
+        if (direction == AudioManager.ADJUST_RAISE) {
+            if (volume == MAX_MASTER_VOLUME) {
+                return 0;
+            }
+            // This is the default value if we make it to the end
+            delta = mMasterVolumeRamp[1];
+            // If we're raising the volume move down the ramp array until we
+            // find the volume we're above and use that groups delta.
+            for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) {
+                if (volume >= mMasterVolumeRamp[i - 1]) {
+                    delta = mMasterVolumeRamp[i];
+                    break;
+                }
+            }
+        } else if (direction == AudioManager.ADJUST_LOWER){
+            if (volume == 0) {
+                return 0;
+            }
+            int length = mMasterVolumeRamp.length;
+            // This is the default value if we make it to the end
+            delta = -mMasterVolumeRamp[length - 1];
+            // If we're lowering the volume move up the ramp array until we
+            // find the volume we're below and use the group below it's delta
+            for (int i = 2; i < length; i += 2) {
+                if (volume <= mMasterVolumeRamp[i]) {
+                    delta = -mMasterVolumeRamp[i - 1];
+                    break;
+                }
+            }
+        }
+        return delta;
+    }
+
     // UI update and Broadcast Intent
     private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
         if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) {
@@ -1862,6 +1890,12 @@
         }
     }
 
+    private void ensureValidSteps(int steps) {
+        if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {
+            throw new IllegalArgumentException("Bad volume adjust steps " + steps);
+        }
+    }
+
     private void ensureValidStreamType(int streamType) {
         if (streamType < 0 || streamType >= mStreamStates.length) {
             throw new IllegalArgumentException("Bad stream type " + streamType);
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
index 688e180..d1cf8b5 100755
--- a/media/jni/mediaeditor/Android.mk
+++ b/media/jni/mediaeditor/Android.mk
@@ -38,12 +38,12 @@
     $(call include-path-for, corecg graphics) \
     $(TOP)/frameworks/native/include/media/editor \
     $(TOP)/frameworks/base/core/jni/mediaeditor \
-    $(TOP)/frameworks/media/libvideoeditor/vss/inc \
-    $(TOP)/frameworks/media/libvideoeditor/vss/common/inc \
-    $(TOP)/frameworks/media/libvideoeditor/vss/mcs/inc \
-    $(TOP)/frameworks/media/libvideoeditor/vss/stagefrightshells/inc \
-    $(TOP)/frameworks/media/libvideoeditor/lvpp \
-    $(TOP)/frameworks/media/libvideoeditor/osal/inc \
+    $(TOP)/frameworks/av/libvideoeditor/vss/inc \
+    $(TOP)/frameworks/av/libvideoeditor/vss/common/inc \
+    $(TOP)/frameworks/av/libvideoeditor/vss/mcs/inc \
+    $(TOP)/frameworks/av/libvideoeditor/vss/stagefrightshells/inc \
+    $(TOP)/frameworks/av/libvideoeditor/lvpp \
+    $(TOP)/frameworks/av/libvideoeditor/osal/inc \
     $(TOP)/frameworks/native/include/media/openmax
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 43008d4..21e8f29 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -3,26 +3,47 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
+    AudioParameter.cpp
+LOCAL_MODULE:= libmedia_helper
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    AudioTrack.cpp \
+    IAudioFlinger.cpp \
+    IAudioFlingerClient.cpp \
+    IAudioTrack.cpp \
+    IAudioRecord.cpp \
+    AudioRecord.cpp \
+    AudioSystem.cpp \
+    mediaplayer.cpp \
+    IMediaPlayerService.cpp \
+    IMediaPlayerClient.cpp \
+    IMediaRecorderClient.cpp \
+    IMediaPlayer.cpp \
+    IMediaRecorder.cpp \
+    IStreamSource.cpp \
+    Metadata.cpp \
+    mediarecorder.cpp \
+    IMediaMetadataRetriever.cpp \
+    mediametadataretriever.cpp \
+    ToneGenerator.cpp \
+    JetPlayer.cpp \
+    IOMX.cpp \
+    IAudioPolicyService.cpp \
+    MediaScanner.cpp \
+    MediaScannerClient.cpp \
     autodetect.cpp \
     IMediaDeathNotifier.cpp \
-    IMediaMetadataRetriever.cpp \
-    IMediaPlayerClient.cpp \
-    IMediaPlayer.cpp \
-    IMediaPlayerService.cpp \
-    IMediaRecorderClient.cpp \
-    IMediaRecorder.cpp \
-    IOMX.cpp \
-    IStreamSource.cpp \
-    JetPlayer.cpp \
-    mediametadataretriever.cpp \
-    mediaplayer.cpp \
     MediaProfiles.cpp \
-    mediarecorder.cpp \
-    MediaScannerClient.cpp \
-    MediaScanner.cpp \
-    MemoryLeakTrackUtil.cpp \
-    Metadata.cpp \
-    Visualizer.cpp
+    IEffect.cpp \
+    IEffectClient.cpp \
+    AudioEffect.cpp \
+    Visualizer.cpp \
+    MemoryLeakTrackUtil.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat \
diff --git a/media/libmedia_native/Android.mk b/media/libmedia_native/Android.mk
index 07f0978..065a90f 100644
--- a/media/libmedia_native/Android.mk
+++ b/media/libmedia_native/Android.mk
@@ -1,39 +1,11 @@
-# FIXME remove "/../libmedia" at same time as rename
-LOCAL_PATH := $(call my-dir)/../libmedia
+LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= \
-    AudioParameter.cpp
-LOCAL_MODULE:= libmedia_helper
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    AudioEffect.cpp \
-    AudioRecord.cpp \
-    AudioSystem.cpp \
-    AudioTrack.cpp \
-    IAudioFlingerClient.cpp \
-    IAudioFlinger.cpp \
-    IAudioPolicyService.cpp \
-    IAudioRecord.cpp \
-    IAudioTrack.cpp \
-    IEffectClient.cpp \
-    IEffect.cpp \
-    ToneGenerator.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libaudioutils libbinder libcutils libutils
+LOCAL_SRC_FILES :=
 
 LOCAL_MODULE:= libmedia_native
 
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils)
-
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 148018d..840e475 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -541,6 +541,12 @@
 }
 
 static player_type getDefaultPlayerType() {
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.use-nuplayer", value, NULL)
+            && (!strcmp("1", value) || !strcasecmp("true", value))) {
+        return NU_PLAYER;
+    }
+
     return STAGEFRIGHT_PLAYER;
 }
 
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 7dbb57f..776d288 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -87,6 +87,7 @@
     sp<MediaMetadataRetrieverBase> p;
     switch (playerType) {
         case STAGEFRIGHT_PLAYER:
+        case NU_PLAYER:
         {
             p = new StagefrightMetadataRetriever;
             break;
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 9b485d7..73336ef 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=                       \
+        GenericSource.cpp               \
         HTTPLiveSource.cpp              \
         NuPlayer.cpp                    \
         NuPlayerDecoder.cpp             \
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
new file mode 100644
index 0000000..99569c9
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -0,0 +1,265 @@
+/*
+ * 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.
+ */
+
+#include "GenericSource.h"
+
+#include "AnotherPacketSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::GenericSource::GenericSource(
+        const char *url,
+        const KeyedVector<String8, String8> *headers,
+        bool uidValid,
+        uid_t uid)
+    : mDurationUs(0ll),
+      mAudioIsVorbis(false) {
+    DataSource::RegisterDefaultSniffers();
+
+    sp<DataSource> dataSource =
+        DataSource::CreateFromURI(url, headers);
+    CHECK(dataSource != NULL);
+
+    initFromDataSource(dataSource);
+}
+
+NuPlayer::GenericSource::GenericSource(
+        int fd, int64_t offset, int64_t length)
+    : mDurationUs(0ll),
+      mAudioIsVorbis(false) {
+    DataSource::RegisterDefaultSniffers();
+
+    sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
+
+    initFromDataSource(dataSource);
+}
+
+void NuPlayer::GenericSource::initFromDataSource(
+        const sp<DataSource> &dataSource) {
+    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+    CHECK(extractor != NULL);
+
+    for (size_t i = 0; i < extractor->countTracks(); ++i) {
+        sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        sp<MediaSource> track;
+
+        if (!strncasecmp(mime, "audio/", 6)) {
+            if (mAudioTrack.mSource == NULL) {
+                mAudioTrack.mSource = track = extractor->getTrack(i);
+
+                if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
+                    mAudioIsVorbis = true;
+                } else {
+                    mAudioIsVorbis = false;
+                }
+            }
+        } else if (!strncasecmp(mime, "video/", 6)) {
+            if (mVideoTrack.mSource == NULL) {
+                mVideoTrack.mSource = track = extractor->getTrack(i);
+            }
+        }
+
+        if (track != NULL) {
+            int64_t durationUs;
+            if (meta->findInt64(kKeyDuration, &durationUs)) {
+                if (durationUs > mDurationUs) {
+                    mDurationUs = durationUs;
+                }
+            }
+        }
+    }
+}
+
+NuPlayer::GenericSource::~GenericSource() {
+}
+
+void NuPlayer::GenericSource::start() {
+    ALOGI("start");
+
+    if (mAudioTrack.mSource != NULL) {
+        CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
+
+        mAudioTrack.mPackets =
+            new AnotherPacketSource(mAudioTrack.mSource->getFormat());
+
+        readBuffer(true /* audio */);
+    }
+
+    if (mVideoTrack.mSource != NULL) {
+        CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
+
+        mVideoTrack.mPackets =
+            new AnotherPacketSource(mVideoTrack.mSource->getFormat());
+
+        readBuffer(false /* audio */);
+    }
+}
+
+status_t NuPlayer::GenericSource::feedMoreTSData() {
+    return OK;
+}
+
+sp<MetaData> NuPlayer::GenericSource::getFormat(bool audio) {
+    sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
+
+    if (source == NULL) {
+        return NULL;
+    }
+
+    return source->getFormat();
+}
+
+status_t NuPlayer::GenericSource::dequeueAccessUnit(
+        bool audio, sp<ABuffer> *accessUnit) {
+    Track *track = audio ? &mAudioTrack : &mVideoTrack;
+
+    if (track->mSource == NULL) {
+        return -EWOULDBLOCK;
+    }
+
+    status_t finalResult;
+    if (!track->mPackets->hasBufferAvailable(&finalResult)) {
+        return finalResult == OK ? -EWOULDBLOCK : finalResult;
+    }
+
+    status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
+
+    readBuffer(audio, -1ll);
+
+    return result;
+}
+
+status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
+    *durationUs = mDurationUs;
+    return OK;
+}
+
+status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
+    if (mVideoTrack.mSource != NULL) {
+        int64_t actualTimeUs;
+        readBuffer(false /* audio */, seekTimeUs, &actualTimeUs);
+
+        seekTimeUs = actualTimeUs;
+    }
+
+    if (mAudioTrack.mSource != NULL) {
+        readBuffer(true /* audio */, seekTimeUs);
+    }
+
+    return OK;
+}
+
+void NuPlayer::GenericSource::readBuffer(
+        bool audio, int64_t seekTimeUs, int64_t *actualTimeUs) {
+    Track *track = audio ? &mAudioTrack : &mVideoTrack;
+    CHECK(track->mSource != NULL);
+
+    if (actualTimeUs) {
+        *actualTimeUs = seekTimeUs;
+    }
+
+    MediaSource::ReadOptions options;
+
+    bool seeking = false;
+
+    if (seekTimeUs >= 0) {
+        options.setSeekTo(seekTimeUs);
+        seeking = true;
+    }
+
+    for (;;) {
+        MediaBuffer *mbuf;
+        status_t err = track->mSource->read(&mbuf, &options);
+
+        options.clearSeekTo();
+
+        if (err == OK) {
+            size_t outLength = mbuf->range_length();
+
+            if (audio && mAudioIsVorbis) {
+                outLength += sizeof(int32_t);
+            }
+
+            sp<ABuffer> buffer = new ABuffer(outLength);
+
+            memcpy(buffer->data(),
+                   (const uint8_t *)mbuf->data() + mbuf->range_offset(),
+                   mbuf->range_length());
+
+            if (audio && mAudioIsVorbis) {
+                int32_t numPageSamples;
+                if (!mbuf->meta_data()->findInt32(
+                            kKeyValidSamples, &numPageSamples)) {
+                    numPageSamples = -1;
+                }
+
+                memcpy(buffer->data() + mbuf->range_length(),
+                       &numPageSamples,
+                       sizeof(numPageSamples));
+            }
+
+            int64_t timeUs;
+            CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+
+            buffer->meta()->setInt64("timeUs", timeUs);
+
+            if (actualTimeUs) {
+                *actualTimeUs = timeUs;
+            }
+
+            mbuf->release();
+            mbuf = NULL;
+
+            if (seeking) {
+                track->mPackets->queueDiscontinuity(
+                        ATSParser::DISCONTINUITY_SEEK, NULL);
+            }
+
+            track->mPackets->queueAccessUnit(buffer);
+            break;
+        } else if (err == INFO_FORMAT_CHANGED) {
+#if 0
+            track->mPackets->queueDiscontinuity(
+                    ATSParser::DISCONTINUITY_FORMATCHANGE, NULL);
+#endif
+        } else {
+            track->mPackets->signalEOS(err);
+            break;
+        }
+    }
+}
+
+bool NuPlayer::GenericSource::isSeekable() {
+    return true;
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
new file mode 100644
index 0000000..aaa5876
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#ifndef GENERIC_SOURCE_H_
+
+#define GENERIC_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+#include "ATSParser.h"
+
+namespace android {
+
+struct AnotherPacketSource;
+struct ARTSPController;
+struct DataSource;
+struct MediaSource;
+
+struct NuPlayer::GenericSource : public NuPlayer::Source {
+    GenericSource(
+            const char *url,
+            const KeyedVector<String8, String8> *headers,
+            bool uidValid = false,
+            uid_t uid = 0);
+
+    GenericSource(int fd, int64_t offset, int64_t length);
+
+    virtual void start();
+
+    virtual status_t feedMoreTSData();
+
+    virtual sp<MetaData> getFormat(bool audio);
+    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+    virtual status_t getDuration(int64_t *durationUs);
+    virtual status_t seekTo(int64_t seekTimeUs);
+    virtual bool isSeekable();
+
+protected:
+    virtual ~GenericSource();
+
+private:
+    struct Track {
+        sp<MediaSource> mSource;
+        sp<AnotherPacketSource> mPackets;
+    };
+
+    Track mAudioTrack;
+    Track mVideoTrack;
+
+    int64_t mDurationUs;
+    bool mAudioIsVorbis;
+
+    void initFromDataSource(const sp<DataSource> &dataSource);
+
+    void readBuffer(
+            bool audio,
+            int64_t seekTimeUs = -1ll, int64_t *actualTimeUs = NULL);
+
+    DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
+};
+
+}  // namespace android
+
+#endif  // GENERIC_SOURCE_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 526120a..544d501 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -27,6 +27,7 @@
 #include "NuPlayerSource.h"
 #include "RTSPSource.h"
 #include "StreamingSource.h"
+#include "GenericSource.h"
 
 #include "ATSParser.h"
 
@@ -84,18 +85,44 @@
     msg->post();
 }
 
+static bool IsHTTPLiveURL(const char *url) {
+    if (!strncasecmp("http://", url, 7)
+            || !strncasecmp("https://", url, 8)) {
+        size_t len = strlen(url);
+        if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
+            return true;
+        }
+
+        if (strstr(url,"m3u8")) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 void NuPlayer::setDataSource(
         const char *url, const KeyedVector<String8, String8> *headers) {
     sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
 
-    if (!strncasecmp(url, "rtsp://", 7)) {
-        msg->setObject(
-                "source", new RTSPSource(url, headers, mUIDValid, mUID));
+    sp<Source> source;
+    if (IsHTTPLiveURL(url)) {
+        source = new HTTPLiveSource(url, headers, mUIDValid, mUID);
+    } else if (!strncasecmp(url, "rtsp://", 7)) {
+        source = new RTSPSource(url, headers, mUIDValid, mUID);
     } else {
-        msg->setObject(
-                "source", new HTTPLiveSource(url, headers, mUIDValid, mUID));
+        source = new GenericSource(url, headers, mUIDValid, mUID);
     }
 
+    msg->setObject("source", source);
+    msg->post();
+}
+
+void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
+    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+
+    sp<Source> source = new GenericSource(fd, offset, length);
+    msg->setObject("source", source);
     msg->post();
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 6be14be..25766e0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -40,6 +40,8 @@
     void setDataSource(
             const char *url, const KeyedVector<String8, String8> *headers);
 
+    void setDataSource(int fd, int64_t offset, int64_t length);
+
     void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
     void start();
@@ -60,12 +62,13 @@
 
 private:
     struct Decoder;
+    struct GenericSource;
     struct HTTPLiveSource;
     struct NuPlayerStreamListener;
     struct Renderer;
+    struct RTSPSource;
     struct Source;
     struct StreamingSource;
-    struct RTSPSource;
 
     enum {
         kWhatSetDataSource              = '=DaS',
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 460fc98..1600141 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -228,6 +228,20 @@
 
         buffer->meta()->setInt32("csd", true);
         mCSD.push(buffer);
+    } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
+        sp<ABuffer> buffer = new ABuffer(size);
+        memcpy(buffer->data(), data, size);
+
+        buffer->meta()->setInt32("csd", true);
+        mCSD.push(buffer);
+
+        CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
+
+        buffer = new ABuffer(size);
+        memcpy(buffer->data(), data, size);
+
+        buffer->meta()->setInt32("csd", true);
+        mCSD.push(buffer);
     }
 
     return msg;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 5aa99bf..253bc2fa 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -76,7 +76,13 @@
 }
 
 status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
-    return INVALID_OPERATION;
+    CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
+    mPlayer->setDataSource(fd, offset, length);
+
+    mState = STOPPED;
+
+    return OK;
 }
 
 status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
@@ -97,13 +103,16 @@
 }
 
 status_t NuPlayerDriver::prepare() {
+    sendEvent(MEDIA_SET_VIDEO_SIZE, 320, 240);
     return OK;
 }
 
 status_t NuPlayerDriver::prepareAsync() {
+    status_t err = prepare();
+
     notifyListener(MEDIA_PREPARED);
 
-    return OK;
+    return err;
 }
 
 status_t NuPlayerDriver::start() {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 5738ecb..ecbc428 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -376,7 +376,8 @@
     bool tooLate = (mVideoLateByUs > 40000);
 
     if (tooLate) {
-        ALOGV("video late by %lld us (%.2f secs)", mVideoLateByUs, mVideoLateByUs / 1E6);
+        ALOGV("video late by %lld us (%.2f secs)",
+             mVideoLateByUs, mVideoLateByUs / 1E6);
     } else {
         ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
     }
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 663f285..9385b8a 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -373,7 +373,8 @@
 
     if (mInitCheck == OK) {
         if (mHasVideo) {
-            mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
+            mFileMetaData->setCString(
+                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
         } else {
             mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
         }
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 2549de6..2740d6b 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -41,7 +41,7 @@
 const char *MEDIA_MIMETYPE_AUDIO_FLAC = "audio/flac";
 const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS = "audio/aac-adts";
 
-const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mpeg4";
+const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
 const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/wav";
 const char *MEDIA_MIMETYPE_CONTAINER_OGG = "application/ogg";
 const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA = "video/x-matroska";
diff --git a/native/copy-to-ndk.sh b/native/copy-to-ndk.sh
index 6470892..90ff556 100644
--- a/native/copy-to-ndk.sh
+++ b/native/copy-to-ndk.sh
@@ -5,7 +5,7 @@
     local CURR_PLATFORM=android-9
     local ALL_PLATFORMS="$CURR_PLATFORM android-8 android-5 android-4 android-3"
 
-    local SRC_HEADERS=$ANDROID_BUILD_TOP/frameworks/base/native/include/android
+    local SRC_HEADERS=$ANDROID_BUILD_TOP/frameworks/native/include/android
     local NDK_PLATFORMS=$ANDROID_BUILD_TOP/development/ndk/platforms
     local DST_HEADERS=$NDK_PLATFORMS/$CURR_PLATFORM
 
diff --git a/native/include/android/asset_manager.h b/native/include/android/asset_manager.h
deleted file mode 100644
index f5df46b..0000000
--- a/native/include/android/asset_manager.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_ASSET_MANAGER_H
-#define ANDROID_ASSET_MANAGER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct AAssetManager;
-typedef struct AAssetManager AAssetManager;
-
-struct AAssetDir;
-typedef struct AAssetDir AAssetDir;
-
-struct AAsset;
-typedef struct AAsset AAsset;
-
-/* Available modes for opening assets */
-enum {
-    AASSET_MODE_UNKNOWN      = 0,
-    AASSET_MODE_RANDOM       = 1,
-    AASSET_MODE_STREAMING    = 2,
-    AASSET_MODE_BUFFER       = 3
-};
-
-
-/**
- * Open the named directory within the asset hierarchy.  The directory can then
- * be inspected with the AAssetDir functions.  To open the top-level directory,
- * pass in "" as the dirName.
- *
- * The object returned here should be freed by calling AAssetDir_close().
- */
-AAssetDir* AAssetManager_openDir(AAssetManager* mgr, const char* dirName);
-
-/**
- * Open an asset.
- *
- * The object returned here should be freed by calling AAsset_close().
- */
-AAsset* AAssetManager_open(AAssetManager* mgr, const char* filename, int mode);
-
-/**
- * Iterate over the files in an asset directory.  A NULL string is returned
- * when all the file names have been returned.
- *
- * The returned file name is suitable for passing to AAssetManager_open().
- *
- * The string returned here is owned by the AssetDir implementation and is not
- * guaranteed to remain valid if any other calls are made on this AAssetDir
- * instance.
- */
-const char* AAssetDir_getNextFileName(AAssetDir* assetDir);
-
-/**
- * Reset the iteration state of AAssetDir_getNextFileName() to the beginning.
- */
-void AAssetDir_rewind(AAssetDir* assetDir);
-
-/**
- * Close an opened AAssetDir, freeing any related resources.
- */
-void AAssetDir_close(AAssetDir* assetDir);
-
-/**
- * Attempt to read 'count' bytes of data from the current offset.
- *
- * Returns the number of bytes read, zero on EOF, or < 0 on error.
- */
-int AAsset_read(AAsset* asset, void* buf, size_t count);
-
-/**
- * Seek to the specified offset within the asset data.  'whence' uses the
- * same constants as lseek()/fseek().
- *
- * Returns the new position on success, or (off_t) -1 on error.
- */
-off_t AAsset_seek(AAsset* asset, off_t offset, int whence);
-
-/**
- * Seek to the specified offset within the asset data.  'whence' uses the
- * same constants as lseek()/fseek().
- *
- * Uses 64-bit data type for large files as opposed to the 32-bit type used
- * by AAsset_seek.
- *
- * Returns the new position on success, or (off64_t) -1 on error.
- */
-off64_t AAsset_seek64(AAsset* asset, off64_t offset, int whence);
-
-/**
- * Close the asset, freeing all associated resources.
- */
-void AAsset_close(AAsset* asset);
-
-/**
- * Get a pointer to a buffer holding the entire contents of the assset.
- *
- * Returns NULL on failure.
- */
-const void* AAsset_getBuffer(AAsset* asset);
-
-/**
- * Report the total size of the asset data.
- */
-off_t AAsset_getLength(AAsset* asset);
-
-/**
- * Report the total size of the asset data. Reports the size using a 64-bit
- * number insted of 32-bit as AAsset_getLength.
- */
-off64_t AAsset_getLength64(AAsset* asset);
-
-/**
- * Report the total amount of asset data that can be read from the current position.
- */
-off_t AAsset_getRemainingLength(AAsset* asset);
-
-/**
- * Report the total amount of asset data that can be read from the current position.
- *
- * Uses a 64-bit number instead of a 32-bit number as AAsset_getRemainingLength does.
- */
-off64_t AAsset_getRemainingLength64(AAsset* asset);
-
-/**
- * Open a new file descriptor that can be used to read the asset data. If the
- * start or length cannot be represented by a 32-bit number, it will be
- * truncated. If the file is large, use AAsset_openFileDescriptor64 instead.
- *
- * Returns < 0 if direct fd access is not possible (for example, if the asset is
- * compressed).
- */
-int AAsset_openFileDescriptor(AAsset* asset, off_t* outStart, off_t* outLength);
-
-/**
- * Open a new file descriptor that can be used to read the asset data.
- *
- * Uses a 64-bit number for the offset and length instead of 32-bit instead of
- * as AAsset_openFileDescriptor does.
- *
- * Returns < 0 if direct fd access is not possible (for example, if the asset is
- * compressed).
- */
-int AAsset_openFileDescriptor64(AAsset* asset, off64_t* outStart, off64_t* outLength);
-
-/**
- * Returns whether this asset's internal buffer is allocated in ordinary RAM (i.e. not
- * mmapped).
- */
-int AAsset_isAllocated(AAsset* asset);
-
-
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif      // ANDROID_ASSET_MANAGER_H
diff --git a/native/include/android/asset_manager_jni.h b/native/include/android/asset_manager_jni.h
deleted file mode 100644
index aec2d3c..0000000
--- a/native/include/android/asset_manager_jni.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_ASSET_MANAGER_JNI_H
-#define ANDROID_ASSET_MANAGER_JNI_H
-
-#include <android/asset_manager.h>
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Given a Dalvik AssetManager object, obtain the corresponding native AAssetManager
- * object.  Note that the caller is responsible for obtaining and holding a VM reference
- * to the jobject to prevent its being garbage collected while the native object is
- * in use.
- */
-AAssetManager* AAssetManager_fromJava(JNIEnv* env, jobject assetManager);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif      // ANDROID_ASSET_MANAGER_JNI_H
diff --git a/native/include/android/bitmap.h b/native/include/android/bitmap.h
deleted file mode 100644
index 5078277..0000000
--- a/native/include/android/bitmap.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef ANDROID_BITMAP_H
-#define ANDROID_BITMAP_H
-
-#include <stdint.h>
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ANDROID_BITMAP_RESUT_SUCCESS            0
-#define ANDROID_BITMAP_RESULT_BAD_PARAMETER     -1
-#define ANDROID_BITMAP_RESULT_JNI_EXCEPTION     -2
-#define ANDROID_BITMAP_RESULT_ALLOCATION_FAILED -3
-
-enum AndroidBitmapFormat {
-    ANDROID_BITMAP_FORMAT_NONE      = 0,
-    ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,
-    ANDROID_BITMAP_FORMAT_RGB_565   = 4,
-    ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
-    ANDROID_BITMAP_FORMAT_A_8       = 8,
-};
-
-typedef struct {
-    uint32_t    width;
-    uint32_t    height;
-    uint32_t    stride;
-    int32_t     format;
-    uint32_t    flags;      // 0 for now
-} AndroidBitmapInfo;
-
-/**
- * Given a java bitmap object, fill out the AndroidBitmap struct for it.
- * If the call fails, the info parameter will be ignored
- */
-int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
-                          AndroidBitmapInfo* info);
-
-/**
- * Given a java bitmap object, attempt to lock the pixel address.
- * Locking will ensure that the memory for the pixels will not move
- * until the unlockPixels call, and ensure that, if the pixels had been
- * previously purged, they will have been restored.
- *
- * If this call succeeds, it must be balanced by a call to
- * AndroidBitmap_unlockPixels, after which time the address of the pixels should
- * no longer be used.
- *
- * If this succeeds, *addrPtr will be set to the pixel address. If the call
- * fails, addrPtr will be ignored.
- */
-int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);
-
-/**
- * Call this to balanace a successful call to AndroidBitmap_lockPixels
- */
-int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/native/include/android/configuration.h b/native/include/android/configuration.h
deleted file mode 100644
index 06cd3da..0000000
--- a/native/include/android/configuration.h
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_CONFIGURATION_H
-#define ANDROID_CONFIGURATION_H
-
-#include <android/asset_manager.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct AConfiguration;
-typedef struct AConfiguration AConfiguration;
-
-enum {
-    ACONFIGURATION_ORIENTATION_ANY  = 0x0000,
-    ACONFIGURATION_ORIENTATION_PORT = 0x0001,
-    ACONFIGURATION_ORIENTATION_LAND = 0x0002,
-    ACONFIGURATION_ORIENTATION_SQUARE = 0x0003,
-
-    ACONFIGURATION_TOUCHSCREEN_ANY  = 0x0000,
-    ACONFIGURATION_TOUCHSCREEN_NOTOUCH  = 0x0001,
-    ACONFIGURATION_TOUCHSCREEN_STYLUS  = 0x0002,
-    ACONFIGURATION_TOUCHSCREEN_FINGER  = 0x0003,
-
-    ACONFIGURATION_DENSITY_DEFAULT = 0,
-    ACONFIGURATION_DENSITY_LOW = 120,
-    ACONFIGURATION_DENSITY_MEDIUM = 160,
-    ACONFIGURATION_DENSITY_TV = 213,
-    ACONFIGURATION_DENSITY_HIGH = 240,
-    ACONFIGURATION_DENSITY_XHIGH = 320,
-    ACONFIGURATION_DENSITY_XXHIGH = 480,
-    ACONFIGURATION_DENSITY_NONE = 0xffff,
-
-    ACONFIGURATION_KEYBOARD_ANY  = 0x0000,
-    ACONFIGURATION_KEYBOARD_NOKEYS  = 0x0001,
-    ACONFIGURATION_KEYBOARD_QWERTY  = 0x0002,
-    ACONFIGURATION_KEYBOARD_12KEY  = 0x0003,
-
-    ACONFIGURATION_NAVIGATION_ANY  = 0x0000,
-    ACONFIGURATION_NAVIGATION_NONAV  = 0x0001,
-    ACONFIGURATION_NAVIGATION_DPAD  = 0x0002,
-    ACONFIGURATION_NAVIGATION_TRACKBALL  = 0x0003,
-    ACONFIGURATION_NAVIGATION_WHEEL  = 0x0004,
-
-    ACONFIGURATION_KEYSHIDDEN_ANY = 0x0000,
-    ACONFIGURATION_KEYSHIDDEN_NO = 0x0001,
-    ACONFIGURATION_KEYSHIDDEN_YES = 0x0002,
-    ACONFIGURATION_KEYSHIDDEN_SOFT = 0x0003,
-
-    ACONFIGURATION_NAVHIDDEN_ANY = 0x0000,
-    ACONFIGURATION_NAVHIDDEN_NO = 0x0001,
-    ACONFIGURATION_NAVHIDDEN_YES = 0x0002,
-
-    ACONFIGURATION_SCREENSIZE_ANY  = 0x00,
-    ACONFIGURATION_SCREENSIZE_SMALL = 0x01,
-    ACONFIGURATION_SCREENSIZE_NORMAL = 0x02,
-    ACONFIGURATION_SCREENSIZE_LARGE = 0x03,
-    ACONFIGURATION_SCREENSIZE_XLARGE = 0x04,
-
-    ACONFIGURATION_SCREENLONG_ANY = 0x00,
-    ACONFIGURATION_SCREENLONG_NO = 0x1,
-    ACONFIGURATION_SCREENLONG_YES = 0x2,
-
-    ACONFIGURATION_UI_MODE_TYPE_ANY = 0x00,
-    ACONFIGURATION_UI_MODE_TYPE_NORMAL = 0x01,
-    ACONFIGURATION_UI_MODE_TYPE_DESK = 0x02,
-    ACONFIGURATION_UI_MODE_TYPE_CAR = 0x03,
-    ACONFIGURATION_UI_MODE_TYPE_TELEVISION = 0x04,
-    ACONFIGURATION_UI_MODE_TYPE_APPLIANCE = 0x05,
-
-    ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00,
-    ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1,
-    ACONFIGURATION_UI_MODE_NIGHT_YES = 0x2,
-
-    ACONFIGURATION_SCREEN_WIDTH_DP_ANY = 0x0000,
-
-    ACONFIGURATION_SCREEN_HEIGHT_DP_ANY = 0x0000,
-
-    ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY = 0x0000,
-
-    ACONFIGURATION_MCC = 0x0001,
-    ACONFIGURATION_MNC = 0x0002,
-    ACONFIGURATION_LOCALE = 0x0004,
-    ACONFIGURATION_TOUCHSCREEN = 0x0008,
-    ACONFIGURATION_KEYBOARD = 0x0010,
-    ACONFIGURATION_KEYBOARD_HIDDEN = 0x0020,
-    ACONFIGURATION_NAVIGATION = 0x0040,
-    ACONFIGURATION_ORIENTATION = 0x0080,
-    ACONFIGURATION_DENSITY = 0x0100,
-    ACONFIGURATION_SCREEN_SIZE = 0x0200,
-    ACONFIGURATION_VERSION = 0x0400,
-    ACONFIGURATION_SCREEN_LAYOUT = 0x0800,
-    ACONFIGURATION_UI_MODE = 0x1000,
-    ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000,
-};
-
-/**
- * Create a new AConfiguration, initialized with no values set.
- */
-AConfiguration* AConfiguration_new();
-
-/**
- * Free an AConfiguration that was previously created with
- * AConfiguration_new().
- */
-void AConfiguration_delete(AConfiguration* config);
-
-/**
- * Create and return a new AConfiguration based on the current configuration in
- * use in the given AssetManager.
- */
-void AConfiguration_fromAssetManager(AConfiguration* out, AAssetManager* am);
-
-/**
- * Copy the contents of 'src' to 'dest'.
- */
-void AConfiguration_copy(AConfiguration* dest, AConfiguration* src);
-
-/**
- * Return the current MCC set in the configuration.  0 if not set.
- */
-int32_t AConfiguration_getMcc(AConfiguration* config);
-
-/**
- * Set the current MCC in the configuration.  0 to clear.
- */
-void AConfiguration_setMcc(AConfiguration* config, int32_t mcc);
-
-/**
- * Return the current MNC set in the configuration.  0 if not set.
- */
-int32_t AConfiguration_getMnc(AConfiguration* config);
-
-/**
- * Set the current MNC in the configuration.  0 to clear.
- */
-void AConfiguration_setMnc(AConfiguration* config, int32_t mnc);
-
-/**
- * Return the current language code set in the configuration.  The output will
- * be filled with an array of two characters.  They are not 0-terminated.  If
- * a language is not set, they will be 0.
- */
-void AConfiguration_getLanguage(AConfiguration* config, char* outLanguage);
-
-/**
- * Set the current language code in the configuration, from the first two
- * characters in the string.
- */
-void AConfiguration_setLanguage(AConfiguration* config, const char* language);
-
-/**
- * Return the current country code set in the configuration.  The output will
- * be filled with an array of two characters.  They are not 0-terminated.  If
- * a country is not set, they will be 0.
- */
-void AConfiguration_getCountry(AConfiguration* config, char* outCountry);
-
-/**
- * Set the current country code in the configuration, from the first two
- * characters in the string.
- */
-void AConfiguration_setCountry(AConfiguration* config, const char* country);
-
-/**
- * Return the current ACONFIGURATION_ORIENTATION_* set in the configuration.
- */
-int32_t AConfiguration_getOrientation(AConfiguration* config);
-
-/**
- * Set the current orientation in the configuration.
- */
-void AConfiguration_setOrientation(AConfiguration* config, int32_t orientation);
-
-/**
- * Return the current ACONFIGURATION_TOUCHSCREEN_* set in the configuration.
- */
-int32_t AConfiguration_getTouchscreen(AConfiguration* config);
-
-/**
- * Set the current touchscreen in the configuration.
- */
-void AConfiguration_setTouchscreen(AConfiguration* config, int32_t touchscreen);
-
-/**
- * Return the current ACONFIGURATION_DENSITY_* set in the configuration.
- */
-int32_t AConfiguration_getDensity(AConfiguration* config);
-
-/**
- * Set the current density in the configuration.
- */
-void AConfiguration_setDensity(AConfiguration* config, int32_t density);
-
-/**
- * Return the current ACONFIGURATION_KEYBOARD_* set in the configuration.
- */
-int32_t AConfiguration_getKeyboard(AConfiguration* config);
-
-/**
- * Set the current keyboard in the configuration.
- */
-void AConfiguration_setKeyboard(AConfiguration* config, int32_t keyboard);
-
-/**
- * Return the current ACONFIGURATION_NAVIGATION_* set in the configuration.
- */
-int32_t AConfiguration_getNavigation(AConfiguration* config);
-
-/**
- * Set the current navigation in the configuration.
- */
-void AConfiguration_setNavigation(AConfiguration* config, int32_t navigation);
-
-/**
- * Return the current ACONFIGURATION_KEYSHIDDEN_* set in the configuration.
- */
-int32_t AConfiguration_getKeysHidden(AConfiguration* config);
-
-/**
- * Set the current keys hidden in the configuration.
- */
-void AConfiguration_setKeysHidden(AConfiguration* config, int32_t keysHidden);
-
-/**
- * Return the current ACONFIGURATION_NAVHIDDEN_* set in the configuration.
- */
-int32_t AConfiguration_getNavHidden(AConfiguration* config);
-
-/**
- * Set the current nav hidden in the configuration.
- */
-void AConfiguration_setNavHidden(AConfiguration* config, int32_t navHidden);
-
-/**
- * Return the current SDK (API) version set in the configuration.
- */
-int32_t AConfiguration_getSdkVersion(AConfiguration* config);
-
-/**
- * Set the current SDK version in the configuration.
- */
-void AConfiguration_setSdkVersion(AConfiguration* config, int32_t sdkVersion);
-
-/**
- * Return the current ACONFIGURATION_SCREENSIZE_* set in the configuration.
- */
-int32_t AConfiguration_getScreenSize(AConfiguration* config);
-
-/**
- * Set the current screen size in the configuration.
- */
-void AConfiguration_setScreenSize(AConfiguration* config, int32_t screenSize);
-
-/**
- * Return the current ACONFIGURATION_SCREENLONG_* set in the configuration.
- */
-int32_t AConfiguration_getScreenLong(AConfiguration* config);
-
-/**
- * Set the current screen long in the configuration.
- */
-void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong);
-
-/**
- * Return the current ACONFIGURATION_UI_MODE_TYPE_* set in the configuration.
- */
-int32_t AConfiguration_getUiModeType(AConfiguration* config);
-
-/**
- * Set the current UI mode type in the configuration.
- */
-void AConfiguration_setUiModeType(AConfiguration* config, int32_t uiModeType);
-
-/**
- * Return the current ACONFIGURATION_UI_MODE_NIGHT_* set in the configuration.
- */
-int32_t AConfiguration_getUiModeNight(AConfiguration* config);
-
-/**
- * Set the current UI mode night in the configuration.
- */
-void AConfiguration_setUiModeNight(AConfiguration* config, int32_t uiModeNight);
-
-/**
- * Return the current configuration screen width in dp units, or
- * ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
- */
-int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
-
-/**
- * Set the configuration's current screen width in dp units.
- */
-void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
-
-/**
- * Return the current configuration screen height in dp units, or
- * ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
- */
-int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
-
-/**
- * Set the configuration's current screen width in dp units.
- */
-void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
-
-/**
- * Return the configuration's smallest screen width in dp units, or
- * ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
- */
-int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
-
-/**
- * Set the configuration's smallest screen width in dp units.
- */
-void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
-
-/**
- * Perform a diff between two configurations.  Returns a bit mask of
- * ACONFIGURATION_* constants, each bit set meaning that configuration element
- * is different between them.
- */
-int32_t AConfiguration_diff(AConfiguration* config1, AConfiguration* config2);
-
-/**
- * Determine whether 'base' is a valid configuration for use within the
- * environment 'requested'.  Returns 0 if there are any values in 'base'
- * that conflict with 'requested'.  Returns 1 if it does not conflict.
- */
-int32_t AConfiguration_match(AConfiguration* base, AConfiguration* requested);
-
-/**
- * Determine whether the configuration in 'test' is better than the existing
- * configuration in 'base'.  If 'requested' is non-NULL, this decision is based
- * on the overall configuration given there.  If it is NULL, this decision is
- * simply based on which configuration is more specific.  Returns non-0 if
- * 'test' is better than 'base'.
- *
- * This assumes you have already filtered the configurations with
- * AConfiguration_match().
- */
-int32_t AConfiguration_isBetterThan(AConfiguration* base, AConfiguration* test,
-        AConfiguration* requested);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif // ANDROID_CONFIGURATION_H
diff --git a/native/include/android/input.h b/native/include/android/input.h
deleted file mode 100644
index f2befa9e..0000000
--- a/native/include/android/input.h
+++ /dev/null
@@ -1,848 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef _ANDROID_INPUT_H
-#define _ANDROID_INPUT_H
-
-/******************************************************************
- *
- * IMPORTANT NOTICE:
- *
- *   This file is part of Android's set of stable system headers
- *   exposed by the Android NDK (Native Development Kit).
- *
- *   Third-party source AND binary code relies on the definitions
- *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
- *
- *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
- *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
- *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
- *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
- */
-
-/*
- * Structures and functions to receive and process input events in
- * native code.
- *
- * NOTE: These functions MUST be implemented by /system/lib/libui.so
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <android/keycodes.h>
-#include <android/looper.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Key states (may be returned by queries about the current state of a
- * particular key code, scan code or switch).
- */
-enum {
-    /* The key state is unknown or the requested key itself is not supported. */
-    AKEY_STATE_UNKNOWN = -1,
-
-    /* The key is up. */
-    AKEY_STATE_UP = 0,
-
-    /* The key is down. */
-    AKEY_STATE_DOWN = 1,
-
-    /* The key is down but is a virtual key press that is being emulated by the system. */
-    AKEY_STATE_VIRTUAL = 2
-};
-
-/*
- * Meta key / modifer state.
- */
-enum {
-    /* No meta keys are pressed. */
-    AMETA_NONE = 0,
-
-    /* This mask is used to check whether one of the ALT meta keys is pressed. */
-    AMETA_ALT_ON = 0x02,
-
-    /* This mask is used to check whether the left ALT meta key is pressed. */
-    AMETA_ALT_LEFT_ON = 0x10,
-
-    /* This mask is used to check whether the right ALT meta key is pressed. */
-    AMETA_ALT_RIGHT_ON = 0x20,
-
-    /* This mask is used to check whether one of the SHIFT meta keys is pressed. */
-    AMETA_SHIFT_ON = 0x01,
-
-    /* This mask is used to check whether the left SHIFT meta key is pressed. */
-    AMETA_SHIFT_LEFT_ON = 0x40,
-
-    /* This mask is used to check whether the right SHIFT meta key is pressed. */
-    AMETA_SHIFT_RIGHT_ON = 0x80,
-
-    /* This mask is used to check whether the SYM meta key is pressed. */
-    AMETA_SYM_ON = 0x04,
-
-    /* This mask is used to check whether the FUNCTION meta key is pressed. */
-    AMETA_FUNCTION_ON = 0x08,
-
-    /* This mask is used to check whether one of the CTRL meta keys is pressed. */
-    AMETA_CTRL_ON = 0x1000,
-
-    /* This mask is used to check whether the left CTRL meta key is pressed. */
-    AMETA_CTRL_LEFT_ON = 0x2000,
-
-    /* This mask is used to check whether the right CTRL meta key is pressed. */
-    AMETA_CTRL_RIGHT_ON = 0x4000,
-
-    /* This mask is used to check whether one of the META meta keys is pressed. */
-    AMETA_META_ON = 0x10000,
-
-    /* This mask is used to check whether the left META meta key is pressed. */
-    AMETA_META_LEFT_ON = 0x20000,
-
-    /* This mask is used to check whether the right META meta key is pressed. */
-    AMETA_META_RIGHT_ON = 0x40000,
-
-    /* This mask is used to check whether the CAPS LOCK meta key is on. */
-    AMETA_CAPS_LOCK_ON = 0x100000,
-
-    /* This mask is used to check whether the NUM LOCK meta key is on. */
-    AMETA_NUM_LOCK_ON = 0x200000,
-
-    /* This mask is used to check whether the SCROLL LOCK meta key is on. */
-    AMETA_SCROLL_LOCK_ON = 0x400000,
-};
-
-/*
- * Input events.
- *
- * Input events are opaque structures.  Use the provided accessors functions to
- * read their properties.
- */
-struct AInputEvent;
-typedef struct AInputEvent AInputEvent;
-
-/*
- * Input event types.
- */
-enum {
-    /* Indicates that the input event is a key event. */
-    AINPUT_EVENT_TYPE_KEY = 1,
-
-    /* Indicates that the input event is a motion event. */
-    AINPUT_EVENT_TYPE_MOTION = 2
-};
-
-/*
- * Key event actions.
- */
-enum {
-    /* The key has been pressed down. */
-    AKEY_EVENT_ACTION_DOWN = 0,
-
-    /* The key has been released. */
-    AKEY_EVENT_ACTION_UP = 1,
-
-    /* Multiple duplicate key events have occurred in a row, or a complex string is
-     * being delivered.  The repeat_count property of the key event contains the number
-     * of times the given key code should be executed.
-     */
-    AKEY_EVENT_ACTION_MULTIPLE = 2
-};
-
-/*
- * Key event flags.
- */
-enum {
-    /* This mask is set if the device woke because of this key event. */
-    AKEY_EVENT_FLAG_WOKE_HERE = 0x1,
-
-    /* This mask is set if the key event was generated by a software keyboard. */
-    AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2,
-
-    /* This mask is set if we don't want the key event to cause us to leave touch mode. */
-    AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4,
-
-    /* This mask is set if an event was known to come from a trusted part
-     * of the system.  That is, the event is known to come from the user,
-     * and could not have been spoofed by a third party component. */
-    AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8,
-
-    /* This mask is used for compatibility, to identify enter keys that are
-     * coming from an IME whose enter key has been auto-labelled "next" or
-     * "done".  This allows TextView to dispatch these as normal enter keys
-     * for old applications, but still do the appropriate action when
-     * receiving them. */
-    AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10,
-
-    /* When associated with up key events, this indicates that the key press
-     * has been canceled.  Typically this is used with virtual touch screen
-     * keys, where the user can slide from the virtual key area on to the
-     * display: in that case, the application will receive a canceled up
-     * event and should not perform the action normally associated with the
-     * key.  Note that for this to work, the application can not perform an
-     * action for a key until it receives an up or the long press timeout has
-     * expired. */
-    AKEY_EVENT_FLAG_CANCELED = 0x20,
-
-    /* This key event was generated by a virtual (on-screen) hard key area.
-     * Typically this is an area of the touchscreen, outside of the regular
-     * display, dedicated to "hardware" buttons. */
-    AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40,
-
-    /* This flag is set for the first key repeat that occurs after the
-     * long press timeout. */
-    AKEY_EVENT_FLAG_LONG_PRESS = 0x80,
-
-    /* Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long
-     * press action was executed while it was down. */
-    AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100,
-
-    /* Set for AKEY_EVENT_ACTION_UP when this event's key code is still being
-     * tracked from its initial down.  That is, somebody requested that tracking
-     * started on the key down and a long press has not caused
-     * the tracking to be canceled. */
-    AKEY_EVENT_FLAG_TRACKING = 0x200,
-
-    /* Set when a key event has been synthesized to implement default behavior
-     * for an event that the application did not handle.
-     * Fallback key events are generated by unhandled trackball motions
-     * (to emulate a directional keypad) and by certain unhandled key presses
-     * that are declared in the key map (such as special function numeric keypad
-     * keys when numlock is off). */
-    AKEY_EVENT_FLAG_FALLBACK = 0x400,
-};
-
-/*
- * Motion event actions.
- */
-
-/* Bit shift for the action bits holding the pointer index as
- * defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK.
- */
-#define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8
-
-enum {
-    /* Bit mask of the parts of the action code that are the action itself.
-     */
-    AMOTION_EVENT_ACTION_MASK = 0xff,
-
-    /* Bits in the action code that represent a pointer index, used with
-     * AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP.  Shifting
-     * down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer
-     * index where the data for the pointer going up or down can be found.
-     */
-    AMOTION_EVENT_ACTION_POINTER_INDEX_MASK  = 0xff00,
-
-    /* A pressed gesture has started, the motion contains the initial starting location.
-     */
-    AMOTION_EVENT_ACTION_DOWN = 0,
-
-    /* A pressed gesture has finished, the motion contains the final release location
-     * as well as any intermediate points since the last down or move event.
-     */
-    AMOTION_EVENT_ACTION_UP = 1,
-
-    /* A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
-     * AMOTION_EVENT_ACTION_UP).  The motion contains the most recent point, as well as
-     * any intermediate points since the last down or move event.
-     */
-    AMOTION_EVENT_ACTION_MOVE = 2,
-
-    /* The current gesture has been aborted.
-     * You will not receive any more points in it.  You should treat this as
-     * an up event, but not perform any action that you normally would.
-     */
-    AMOTION_EVENT_ACTION_CANCEL = 3,
-
-    /* A movement has happened outside of the normal bounds of the UI element.
-     * This does not provide a full gesture, but only the initial location of the movement/touch.
-     */
-    AMOTION_EVENT_ACTION_OUTSIDE = 4,
-
-    /* A non-primary pointer has gone down.
-     * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
-     */
-    AMOTION_EVENT_ACTION_POINTER_DOWN = 5,
-
-    /* A non-primary pointer has gone up.
-     * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
-     */
-    AMOTION_EVENT_ACTION_POINTER_UP = 6,
-
-    /* A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
-     * The motion contains the most recent point, as well as any intermediate points since
-     * the last hover move event.
-     */
-    AMOTION_EVENT_ACTION_HOVER_MOVE = 7,
-
-    /* The motion event contains relative vertical and/or horizontal scroll offsets.
-     * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
-     * and AMOTION_EVENT_AXIS_HSCROLL.
-     * The pointer may or may not be down when this event is dispatched.
-     * This action is always delivered to the winder under the pointer, which
-     * may not be the window currently touched.
-     */
-    AMOTION_EVENT_ACTION_SCROLL = 8,
-
-    /* The pointer is not down but has entered the boundaries of a window or view.
-     */
-    AMOTION_EVENT_ACTION_HOVER_ENTER = 9,
-
-    /* The pointer is not down but has exited the boundaries of a window or view.
-     */
-    AMOTION_EVENT_ACTION_HOVER_EXIT = 10,
-};
-
-/*
- * Motion event flags.
- */
-enum {
-    /* This flag indicates that the window that received this motion event is partly
-     * or wholly obscured by another visible window above it.  This flag is set to true
-     * even if the event did not directly pass through the obscured area.
-     * A security sensitive application can check this flag to identify situations in which
-     * a malicious application may have covered up part of its content for the purpose
-     * of misleading the user or hijacking touches.  An appropriate response might be
-     * to drop the suspect touches or to take additional precautions to confirm the user's
-     * actual intent.
-     */
-    AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1,
-};
-
-/*
- * Motion event edge touch flags.
- */
-enum {
-    /* No edges intersected */
-    AMOTION_EVENT_EDGE_FLAG_NONE = 0,
-
-    /* Flag indicating the motion event intersected the top edge of the screen. */
-    AMOTION_EVENT_EDGE_FLAG_TOP = 0x01,
-
-    /* Flag indicating the motion event intersected the bottom edge of the screen. */
-    AMOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02,
-
-    /* Flag indicating the motion event intersected the left edge of the screen. */
-    AMOTION_EVENT_EDGE_FLAG_LEFT = 0x04,
-
-    /* Flag indicating the motion event intersected the right edge of the screen. */
-    AMOTION_EVENT_EDGE_FLAG_RIGHT = 0x08
-};
-
-/*
- * Constants that identify each individual axis of a motion event.
- * Refer to the documentation on the MotionEvent class for descriptions of each axis.
- */
-enum {
-    AMOTION_EVENT_AXIS_X = 0,
-    AMOTION_EVENT_AXIS_Y = 1,
-    AMOTION_EVENT_AXIS_PRESSURE = 2,
-    AMOTION_EVENT_AXIS_SIZE = 3,
-    AMOTION_EVENT_AXIS_TOUCH_MAJOR = 4,
-    AMOTION_EVENT_AXIS_TOUCH_MINOR = 5,
-    AMOTION_EVENT_AXIS_TOOL_MAJOR = 6,
-    AMOTION_EVENT_AXIS_TOOL_MINOR = 7,
-    AMOTION_EVENT_AXIS_ORIENTATION = 8,
-    AMOTION_EVENT_AXIS_VSCROLL = 9,
-    AMOTION_EVENT_AXIS_HSCROLL = 10,
-    AMOTION_EVENT_AXIS_Z = 11,
-    AMOTION_EVENT_AXIS_RX = 12,
-    AMOTION_EVENT_AXIS_RY = 13,
-    AMOTION_EVENT_AXIS_RZ = 14,
-    AMOTION_EVENT_AXIS_HAT_X = 15,
-    AMOTION_EVENT_AXIS_HAT_Y = 16,
-    AMOTION_EVENT_AXIS_LTRIGGER = 17,
-    AMOTION_EVENT_AXIS_RTRIGGER = 18,
-    AMOTION_EVENT_AXIS_THROTTLE = 19,
-    AMOTION_EVENT_AXIS_RUDDER = 20,
-    AMOTION_EVENT_AXIS_WHEEL = 21,
-    AMOTION_EVENT_AXIS_GAS = 22,
-    AMOTION_EVENT_AXIS_BRAKE = 23,
-    AMOTION_EVENT_AXIS_DISTANCE = 24,
-    AMOTION_EVENT_AXIS_TILT = 25,
-    AMOTION_EVENT_AXIS_GENERIC_1 = 32,
-    AMOTION_EVENT_AXIS_GENERIC_2 = 33,
-    AMOTION_EVENT_AXIS_GENERIC_3 = 34,
-    AMOTION_EVENT_AXIS_GENERIC_4 = 35,
-    AMOTION_EVENT_AXIS_GENERIC_5 = 36,
-    AMOTION_EVENT_AXIS_GENERIC_6 = 37,
-    AMOTION_EVENT_AXIS_GENERIC_7 = 38,
-    AMOTION_EVENT_AXIS_GENERIC_8 = 39,
-    AMOTION_EVENT_AXIS_GENERIC_9 = 40,
-    AMOTION_EVENT_AXIS_GENERIC_10 = 41,
-    AMOTION_EVENT_AXIS_GENERIC_11 = 42,
-    AMOTION_EVENT_AXIS_GENERIC_12 = 43,
-    AMOTION_EVENT_AXIS_GENERIC_13 = 44,
-    AMOTION_EVENT_AXIS_GENERIC_14 = 45,
-    AMOTION_EVENT_AXIS_GENERIC_15 = 46,
-    AMOTION_EVENT_AXIS_GENERIC_16 = 47,
-
-    // NOTE: If you add a new axis here you must also add it to several other files.
-    //       Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
-};
-
-/*
- * Constants that identify buttons that are associated with motion events.
- * Refer to the documentation on the MotionEvent class for descriptions of each button.
- */
-enum {
-    AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
-    AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1,
-    AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
-    AMOTION_EVENT_BUTTON_BACK = 1 << 3,
-    AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
-};
-
-/*
- * Constants that identify tool types.
- * Refer to the documentation on the MotionEvent class for descriptions of each tool type.
- */
-enum {
-    AMOTION_EVENT_TOOL_TYPE_UNKNOWN = 0,
-    AMOTION_EVENT_TOOL_TYPE_FINGER = 1,
-    AMOTION_EVENT_TOOL_TYPE_STYLUS = 2,
-    AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
-    AMOTION_EVENT_TOOL_TYPE_ERASER = 4,
-};
-
-/*
- * Input sources.
- *
- * Refer to the documentation on android.view.InputDevice for more details about input sources
- * and their correct interpretation.
- */
-enum {
-    AINPUT_SOURCE_CLASS_MASK = 0x000000ff,
-
-    AINPUT_SOURCE_CLASS_BUTTON = 0x00000001,
-    AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
-    AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
-    AINPUT_SOURCE_CLASS_POSITION = 0x00000008,
-    AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010,
-};
-
-enum {
-    AINPUT_SOURCE_UNKNOWN = 0x00000000,
-
-    AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON,
-    AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON,
-    AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
-    AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
-    AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
-    AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
-    AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
-    AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
-    AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
-
-    AINPUT_SOURCE_ANY = 0xffffff00,
-};
-
-/*
- * Keyboard types.
- *
- * Refer to the documentation on android.view.InputDevice for more details.
- */
-enum {
-    AINPUT_KEYBOARD_TYPE_NONE = 0,
-    AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC = 1,
-    AINPUT_KEYBOARD_TYPE_ALPHABETIC = 2,
-};
-
-/*
- * Constants used to retrieve information about the range of motion for a particular
- * coordinate of a motion event.
- *
- * Refer to the documentation on android.view.InputDevice for more details about input sources
- * and their correct interpretation.
- *
- * DEPRECATION NOTICE: These constants are deprecated.  Use AMOTION_EVENT_AXIS_* constants instead.
- */
-enum {
-    AINPUT_MOTION_RANGE_X = AMOTION_EVENT_AXIS_X,
-    AINPUT_MOTION_RANGE_Y = AMOTION_EVENT_AXIS_Y,
-    AINPUT_MOTION_RANGE_PRESSURE = AMOTION_EVENT_AXIS_PRESSURE,
-    AINPUT_MOTION_RANGE_SIZE = AMOTION_EVENT_AXIS_SIZE,
-    AINPUT_MOTION_RANGE_TOUCH_MAJOR = AMOTION_EVENT_AXIS_TOUCH_MAJOR,
-    AINPUT_MOTION_RANGE_TOUCH_MINOR = AMOTION_EVENT_AXIS_TOUCH_MINOR,
-    AINPUT_MOTION_RANGE_TOOL_MAJOR = AMOTION_EVENT_AXIS_TOOL_MAJOR,
-    AINPUT_MOTION_RANGE_TOOL_MINOR = AMOTION_EVENT_AXIS_TOOL_MINOR,
-    AINPUT_MOTION_RANGE_ORIENTATION = AMOTION_EVENT_AXIS_ORIENTATION,
-} __attribute__ ((deprecated));
-
-
-/*
- * Input event accessors.
- *
- * Note that most functions can only be used on input events that are of a given type.
- * Calling these functions on input events of other types will yield undefined behavior.
- */
-
-/*** Accessors for all input events. ***/
-
-/* Get the input event type. */
-int32_t AInputEvent_getType(const AInputEvent* event);
-
-/* Get the id for the device that an input event came from.
- *
- * Input events can be generated by multiple different input devices.
- * Use the input device id to obtain information about the input
- * device that was responsible for generating a particular event.
- *
- * An input device id of 0 indicates that the event didn't come from a physical device;
- * other numbers are arbitrary and you shouldn't depend on the values.
- * Use the provided input device query API to obtain information about input devices.
- */
-int32_t AInputEvent_getDeviceId(const AInputEvent* event);
-
-/* Get the input event source. */
-int32_t AInputEvent_getSource(const AInputEvent* event);
-
-/*** Accessors for key events only. ***/
-
-/* Get the key event action. */
-int32_t AKeyEvent_getAction(const AInputEvent* key_event);
-
-/* Get the key event flags. */
-int32_t AKeyEvent_getFlags(const AInputEvent* key_event);
-
-/* Get the key code of the key event.
- * This is the physical key that was pressed, not the Unicode character. */
-int32_t AKeyEvent_getKeyCode(const AInputEvent* key_event);
-
-/* Get the hardware key id of this key event.
- * These values are not reliable and vary from device to device. */
-int32_t AKeyEvent_getScanCode(const AInputEvent* key_event);
-
-/* Get the meta key state. */
-int32_t AKeyEvent_getMetaState(const AInputEvent* key_event);
-
-/* Get the repeat count of the event.
- * For both key up an key down events, this is the number of times the key has
- * repeated with the first down starting at 0 and counting up from there.  For
- * multiple key events, this is the number of down/up pairs that have occurred. */
-int32_t AKeyEvent_getRepeatCount(const AInputEvent* key_event);
-
-/* Get the time of the most recent key down event, in the
- * java.lang.System.nanoTime() time base.  If this is a down event,
- * this will be the same as eventTime.
- * Note that when chording keys, this value is the down time of the most recently
- * pressed key, which may not be the same physical key of this event. */
-int64_t AKeyEvent_getDownTime(const AInputEvent* key_event);
-
-/* Get the time this event occurred, in the
- * java.lang.System.nanoTime() time base. */
-int64_t AKeyEvent_getEventTime(const AInputEvent* key_event);
-
-/*** Accessors for motion events only. ***/
-
-/* Get the combined motion event action code and pointer index. */
-int32_t AMotionEvent_getAction(const AInputEvent* motion_event);
-
-/* Get the motion event flags. */
-int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
-
-/* Get the state of any meta / modifier keys that were in effect when the
- * event was generated. */
-int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
-
-/* Get the button state of all buttons that are pressed. */
-int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
-
-/* Get a bitfield indicating which edges, if any, were touched by this motion event.
- * For touch events, clients can use this to determine if the user's finger was
- * touching the edge of the display. */
-int32_t AMotionEvent_getEdgeFlags(const AInputEvent* motion_event);
-
-/* Get the time when the user originally pressed down to start a stream of
- * position events, in the java.lang.System.nanoTime() time base. */
-int64_t AMotionEvent_getDownTime(const AInputEvent* motion_event);
-
-/* Get the time when this specific event was generated,
- * in the java.lang.System.nanoTime() time base. */
-int64_t AMotionEvent_getEventTime(const AInputEvent* motion_event);
-
-/* Get the X coordinate offset.
- * For touch events on the screen, this is the delta that was added to the raw
- * screen coordinates to adjust for the absolute position of the containing windows
- * and views. */
-float AMotionEvent_getXOffset(const AInputEvent* motion_event);
-
-/* Get the precision of the Y coordinates being reported.
- * For touch events on the screen, this is the delta that was added to the raw
- * screen coordinates to adjust for the absolute position of the containing windows
- * and views. */
-float AMotionEvent_getYOffset(const AInputEvent* motion_event);
-
-/* Get the precision of the X coordinates being reported.
- * You can multiply this number with an X coordinate sample to find the
- * actual hardware value of the X coordinate. */
-float AMotionEvent_getXPrecision(const AInputEvent* motion_event);
-
-/* Get the precision of the Y coordinates being reported.
- * You can multiply this number with a Y coordinate sample to find the
- * actual hardware value of the Y coordinate. */
-float AMotionEvent_getYPrecision(const AInputEvent* motion_event);
-
-/* Get the number of pointers of data contained in this event.
- * Always >= 1. */
-size_t AMotionEvent_getPointerCount(const AInputEvent* motion_event);
-
-/* Get the pointer identifier associated with a particular pointer
- * data index in this event.  The identifier tells you the actual pointer
- * number associated with the data, accounting for individual pointers
- * going up and down since the start of the current gesture. */
-int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the tool type of a pointer for the given pointer index.
- * The tool type indicates the type of tool used to make contact such as a
- * finger or stylus, if known. */
-int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the original raw X coordinate of this event.
- * For touch events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views. */
-float AMotionEvent_getRawX(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the original raw X coordinate of this event.
- * For touch events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views. */
-float AMotionEvent_getRawY(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current X coordinate of this event for the given pointer index.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getX(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current Y coordinate of this event for the given pointer index.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getY(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current pressure of this event for the given pointer index.
- * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
- * although values higher than 1 may be generated depending on the calibration of
- * the input device. */
-float AMotionEvent_getPressure(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current scaled value of the approximate size for the given pointer index.
- * This represents some approximation of the area of the screen being
- * pressed; the actual value in pixels corresponding to the
- * touch is normalized with the device specific range of values
- * and scaled to a value between 0 and 1.  The value of size can be used to
- * determine fat touch events. */
-float AMotionEvent_getSize(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current length of the major axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index. */
-float AMotionEvent_getTouchMajor(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current length of the minor axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index. */
-float AMotionEvent_getTouchMinor(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current length of the major axis of an ellipse that describes the size
- * of the approaching tool for the given pointer index.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
-float AMotionEvent_getToolMajor(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current length of the minor axis of an ellipse that describes the size
- * of the approaching tool for the given pointer index.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
-float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the current orientation of the touch area and tool area in radians clockwise from
- * vertical for the given pointer index.
- * An angle of 0 degrees indicates that the major axis of contact is oriented
- * upwards, is perfectly circular or is of unknown orientation.  A positive angle
- * indicates that the major axis of contact is oriented to the right.  A negative angle
- * indicates that the major axis of contact is oriented to the left.
- * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
- * (finger pointing fully right). */
-float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
-
-/* Get the value of the request axis for the given pointer index. */
-float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
-        int32_t axis, size_t pointer_index);
-
-/* Get the number of historical points in this event.  These are movements that
- * have occurred between this event and the previous event.  This only applies
- * to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0.
- * Historical samples are indexed from oldest to newest. */
-size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event);
-
-/* Get the time that a historical movement occurred between this event and
- * the previous event, in the java.lang.System.nanoTime() time base. */
-int64_t AMotionEvent_getHistoricalEventTime(AInputEvent* motion_event,
-        size_t history_index);
-
-/* Get the historical raw X coordinate of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * For touch events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getHistoricalRawX(const AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical raw Y coordinate of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * For touch events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getHistoricalRawY(const AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical X coordinate of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getHistoricalX(AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical Y coordinate of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
-float AMotionEvent_getHistoricalY(AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical pressure of this event for the given pointer index that
- * occurred between this event and the previous motion event.
- * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
- * although values higher than 1 may be generated depending on the calibration of
- * the input device. */
-float AMotionEvent_getHistoricalPressure(AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the current scaled value of the approximate size for the given pointer index that
- * occurred between this event and the previous motion event.
- * This represents some approximation of the area of the screen being
- * pressed; the actual value in pixels corresponding to the
- * touch is normalized with the device specific range of values
- * and scaled to a value between 0 and 1.  The value of size can be used to
- * determine fat touch events. */
-float AMotionEvent_getHistoricalSize(AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical length of the major axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index that
- * occurred between this event and the previous motion event. */
-float AMotionEvent_getHistoricalTouchMajor(const AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical length of the minor axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index that
- * occurred between this event and the previous motion event. */
-float AMotionEvent_getHistoricalTouchMinor(const AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical length of the major axis of an ellipse that describes the size
- * of the approaching tool for the given pointer index that
- * occurred between this event and the previous motion event.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
-float AMotionEvent_getHistoricalToolMajor(const AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical length of the minor axis of an ellipse that describes the size
- * of the approaching tool for the given pointer index that
- * occurred between this event and the previous motion event.
- * The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
-float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical orientation of the touch area and tool area in radians clockwise from
- * vertical for the given pointer index that
- * occurred between this event and the previous motion event.
- * An angle of 0 degrees indicates that the major axis of contact is oriented
- * upwards, is perfectly circular or is of unknown orientation.  A positive angle
- * indicates that the major axis of contact is oriented to the right.  A negative angle
- * indicates that the major axis of contact is oriented to the left.
- * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
- * (finger pointing fully right). */
-float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
-        size_t history_index);
-
-/* Get the historical value of the request axis for the given pointer index
- * that occurred between this event and the previous motion event. */
-float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
-        int32_t axis, size_t pointer_index, size_t history_index);
-
-
-/*
- * Input queue
- *
- * An input queue is the facility through which you retrieve input
- * events.
- */
-struct AInputQueue;
-typedef struct AInputQueue AInputQueue;
-
-/*
- * Add this input queue to a looper for processing.  See
- * ALooper_addFd() for information on the ident, callback, and data params.
- */
-void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
-        int ident, ALooper_callbackFunc callback, void* data);
-
-/*
- * Remove the input queue from the looper it is currently attached to.
- */
-void AInputQueue_detachLooper(AInputQueue* queue);
-
-/*
- * Returns true if there are one or more events available in the
- * input queue.  Returns 1 if the queue has events; 0 if
- * it does not have events; and a negative value if there is an error.
- */
-int32_t AInputQueue_hasEvents(AInputQueue* queue);
-
-/*
- * Returns the next available event from the queue.  Returns a negative
- * value if no events are available or an error has occurred.
- */
-int32_t AInputQueue_getEvent(AInputQueue* queue, AInputEvent** outEvent);
-
-/*
- * Sends the key for standard pre-dispatching -- that is, possibly deliver
- * it to the current IME to be consumed before the app.  Returns 0 if it
- * was not pre-dispatched, meaning you can process it right now.  If non-zero
- * is returned, you must abandon the current event processing and allow the
- * event to appear again in the event queue (if it does not get consumed during
- * pre-dispatching).
- */
-int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event);
-
-/*
- * Report that dispatching has finished with the given event.
- * This must be called after receiving an event with AInputQueue_get_event().
- */
-void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _ANDROID_INPUT_H
diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h
deleted file mode 100644
index 8414ff6..0000000
--- a/native/include/android/keycodes.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef _ANDROID_KEYCODES_H
-#define _ANDROID_KEYCODES_H
-
-/******************************************************************
- *
- * IMPORTANT NOTICE:
- *
- *   This file is part of Android's set of stable system headers
- *   exposed by the Android NDK (Native Development Kit).
- *
- *   Third-party source AND binary code relies on the definitions
- *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
- *
- *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
- *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
- *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
- *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
- */
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Key codes.
- */
-enum {
-    AKEYCODE_UNKNOWN         = 0,
-    AKEYCODE_SOFT_LEFT       = 1,
-    AKEYCODE_SOFT_RIGHT      = 2,
-    AKEYCODE_HOME            = 3,
-    AKEYCODE_BACK            = 4,
-    AKEYCODE_CALL            = 5,
-    AKEYCODE_ENDCALL         = 6,
-    AKEYCODE_0               = 7,
-    AKEYCODE_1               = 8,
-    AKEYCODE_2               = 9,
-    AKEYCODE_3               = 10,
-    AKEYCODE_4               = 11,
-    AKEYCODE_5               = 12,
-    AKEYCODE_6               = 13,
-    AKEYCODE_7               = 14,
-    AKEYCODE_8               = 15,
-    AKEYCODE_9               = 16,
-    AKEYCODE_STAR            = 17,
-    AKEYCODE_POUND           = 18,
-    AKEYCODE_DPAD_UP         = 19,
-    AKEYCODE_DPAD_DOWN       = 20,
-    AKEYCODE_DPAD_LEFT       = 21,
-    AKEYCODE_DPAD_RIGHT      = 22,
-    AKEYCODE_DPAD_CENTER     = 23,
-    AKEYCODE_VOLUME_UP       = 24,
-    AKEYCODE_VOLUME_DOWN     = 25,
-    AKEYCODE_POWER           = 26,
-    AKEYCODE_CAMERA          = 27,
-    AKEYCODE_CLEAR           = 28,
-    AKEYCODE_A               = 29,
-    AKEYCODE_B               = 30,
-    AKEYCODE_C               = 31,
-    AKEYCODE_D               = 32,
-    AKEYCODE_E               = 33,
-    AKEYCODE_F               = 34,
-    AKEYCODE_G               = 35,
-    AKEYCODE_H               = 36,
-    AKEYCODE_I               = 37,
-    AKEYCODE_J               = 38,
-    AKEYCODE_K               = 39,
-    AKEYCODE_L               = 40,
-    AKEYCODE_M               = 41,
-    AKEYCODE_N               = 42,
-    AKEYCODE_O               = 43,
-    AKEYCODE_P               = 44,
-    AKEYCODE_Q               = 45,
-    AKEYCODE_R               = 46,
-    AKEYCODE_S               = 47,
-    AKEYCODE_T               = 48,
-    AKEYCODE_U               = 49,
-    AKEYCODE_V               = 50,
-    AKEYCODE_W               = 51,
-    AKEYCODE_X               = 52,
-    AKEYCODE_Y               = 53,
-    AKEYCODE_Z               = 54,
-    AKEYCODE_COMMA           = 55,
-    AKEYCODE_PERIOD          = 56,
-    AKEYCODE_ALT_LEFT        = 57,
-    AKEYCODE_ALT_RIGHT       = 58,
-    AKEYCODE_SHIFT_LEFT      = 59,
-    AKEYCODE_SHIFT_RIGHT     = 60,
-    AKEYCODE_TAB             = 61,
-    AKEYCODE_SPACE           = 62,
-    AKEYCODE_SYM             = 63,
-    AKEYCODE_EXPLORER        = 64,
-    AKEYCODE_ENVELOPE        = 65,
-    AKEYCODE_ENTER           = 66,
-    AKEYCODE_DEL             = 67,
-    AKEYCODE_GRAVE           = 68,
-    AKEYCODE_MINUS           = 69,
-    AKEYCODE_EQUALS          = 70,
-    AKEYCODE_LEFT_BRACKET    = 71,
-    AKEYCODE_RIGHT_BRACKET   = 72,
-    AKEYCODE_BACKSLASH       = 73,
-    AKEYCODE_SEMICOLON       = 74,
-    AKEYCODE_APOSTROPHE      = 75,
-    AKEYCODE_SLASH           = 76,
-    AKEYCODE_AT              = 77,
-    AKEYCODE_NUM             = 78,
-    AKEYCODE_HEADSETHOOK     = 79,
-    AKEYCODE_FOCUS           = 80,   // *Camera* focus
-    AKEYCODE_PLUS            = 81,
-    AKEYCODE_MENU            = 82,
-    AKEYCODE_NOTIFICATION    = 83,
-    AKEYCODE_SEARCH          = 84,
-    AKEYCODE_MEDIA_PLAY_PAUSE= 85,
-    AKEYCODE_MEDIA_STOP      = 86,
-    AKEYCODE_MEDIA_NEXT      = 87,
-    AKEYCODE_MEDIA_PREVIOUS  = 88,
-    AKEYCODE_MEDIA_REWIND    = 89,
-    AKEYCODE_MEDIA_FAST_FORWARD = 90,
-    AKEYCODE_MUTE            = 91,
-    AKEYCODE_PAGE_UP         = 92,
-    AKEYCODE_PAGE_DOWN       = 93,
-    AKEYCODE_PICTSYMBOLS     = 94,
-    AKEYCODE_SWITCH_CHARSET  = 95,
-    AKEYCODE_BUTTON_A        = 96,
-    AKEYCODE_BUTTON_B        = 97,
-    AKEYCODE_BUTTON_C        = 98,
-    AKEYCODE_BUTTON_X        = 99,
-    AKEYCODE_BUTTON_Y        = 100,
-    AKEYCODE_BUTTON_Z        = 101,
-    AKEYCODE_BUTTON_L1       = 102,
-    AKEYCODE_BUTTON_R1       = 103,
-    AKEYCODE_BUTTON_L2       = 104,
-    AKEYCODE_BUTTON_R2       = 105,
-    AKEYCODE_BUTTON_THUMBL   = 106,
-    AKEYCODE_BUTTON_THUMBR   = 107,
-    AKEYCODE_BUTTON_START    = 108,
-    AKEYCODE_BUTTON_SELECT   = 109,
-    AKEYCODE_BUTTON_MODE     = 110,
-    AKEYCODE_ESCAPE          = 111,
-    AKEYCODE_FORWARD_DEL     = 112,
-    AKEYCODE_CTRL_LEFT       = 113,
-    AKEYCODE_CTRL_RIGHT      = 114,
-    AKEYCODE_CAPS_LOCK       = 115,
-    AKEYCODE_SCROLL_LOCK     = 116,
-    AKEYCODE_META_LEFT       = 117,
-    AKEYCODE_META_RIGHT      = 118,
-    AKEYCODE_FUNCTION        = 119,
-    AKEYCODE_SYSRQ           = 120,
-    AKEYCODE_BREAK           = 121,
-    AKEYCODE_MOVE_HOME       = 122,
-    AKEYCODE_MOVE_END        = 123,
-    AKEYCODE_INSERT          = 124,
-    AKEYCODE_FORWARD         = 125,
-    AKEYCODE_MEDIA_PLAY      = 126,
-    AKEYCODE_MEDIA_PAUSE     = 127,
-    AKEYCODE_MEDIA_CLOSE     = 128,
-    AKEYCODE_MEDIA_EJECT     = 129,
-    AKEYCODE_MEDIA_RECORD    = 130,
-    AKEYCODE_F1              = 131,
-    AKEYCODE_F2              = 132,
-    AKEYCODE_F3              = 133,
-    AKEYCODE_F4              = 134,
-    AKEYCODE_F5              = 135,
-    AKEYCODE_F6              = 136,
-    AKEYCODE_F7              = 137,
-    AKEYCODE_F8              = 138,
-    AKEYCODE_F9              = 139,
-    AKEYCODE_F10             = 140,
-    AKEYCODE_F11             = 141,
-    AKEYCODE_F12             = 142,
-    AKEYCODE_NUM_LOCK        = 143,
-    AKEYCODE_NUMPAD_0        = 144,
-    AKEYCODE_NUMPAD_1        = 145,
-    AKEYCODE_NUMPAD_2        = 146,
-    AKEYCODE_NUMPAD_3        = 147,
-    AKEYCODE_NUMPAD_4        = 148,
-    AKEYCODE_NUMPAD_5        = 149,
-    AKEYCODE_NUMPAD_6        = 150,
-    AKEYCODE_NUMPAD_7        = 151,
-    AKEYCODE_NUMPAD_8        = 152,
-    AKEYCODE_NUMPAD_9        = 153,
-    AKEYCODE_NUMPAD_DIVIDE   = 154,
-    AKEYCODE_NUMPAD_MULTIPLY = 155,
-    AKEYCODE_NUMPAD_SUBTRACT = 156,
-    AKEYCODE_NUMPAD_ADD      = 157,
-    AKEYCODE_NUMPAD_DOT      = 158,
-    AKEYCODE_NUMPAD_COMMA    = 159,
-    AKEYCODE_NUMPAD_ENTER    = 160,
-    AKEYCODE_NUMPAD_EQUALS   = 161,
-    AKEYCODE_NUMPAD_LEFT_PAREN = 162,
-    AKEYCODE_NUMPAD_RIGHT_PAREN = 163,
-    AKEYCODE_VOLUME_MUTE     = 164,
-    AKEYCODE_INFO            = 165,
-    AKEYCODE_CHANNEL_UP      = 166,
-    AKEYCODE_CHANNEL_DOWN    = 167,
-    AKEYCODE_ZOOM_IN         = 168,
-    AKEYCODE_ZOOM_OUT        = 169,
-    AKEYCODE_TV              = 170,
-    AKEYCODE_WINDOW          = 171,
-    AKEYCODE_GUIDE           = 172,
-    AKEYCODE_DVR             = 173,
-    AKEYCODE_BOOKMARK        = 174,
-    AKEYCODE_CAPTIONS        = 175,
-    AKEYCODE_SETTINGS        = 176,
-    AKEYCODE_TV_POWER        = 177,
-    AKEYCODE_TV_INPUT        = 178,
-    AKEYCODE_STB_POWER       = 179,
-    AKEYCODE_STB_INPUT       = 180,
-    AKEYCODE_AVR_POWER       = 181,
-    AKEYCODE_AVR_INPUT       = 182,
-    AKEYCODE_PROG_RED        = 183,
-    AKEYCODE_PROG_GREEN      = 184,
-    AKEYCODE_PROG_YELLOW     = 185,
-    AKEYCODE_PROG_BLUE       = 186,
-    AKEYCODE_APP_SWITCH      = 187,
-    AKEYCODE_BUTTON_1        = 188,
-    AKEYCODE_BUTTON_2        = 189,
-    AKEYCODE_BUTTON_3        = 190,
-    AKEYCODE_BUTTON_4        = 191,
-    AKEYCODE_BUTTON_5        = 192,
-    AKEYCODE_BUTTON_6        = 193,
-    AKEYCODE_BUTTON_7        = 194,
-    AKEYCODE_BUTTON_8        = 195,
-    AKEYCODE_BUTTON_9        = 196,
-    AKEYCODE_BUTTON_10       = 197,
-    AKEYCODE_BUTTON_11       = 198,
-    AKEYCODE_BUTTON_12       = 199,
-    AKEYCODE_BUTTON_13       = 200,
-    AKEYCODE_BUTTON_14       = 201,
-    AKEYCODE_BUTTON_15       = 202,
-    AKEYCODE_BUTTON_16       = 203,
-    AKEYCODE_LANGUAGE_SWITCH = 204,
-    AKEYCODE_MANNER_MODE     = 205,
-    AKEYCODE_3D_MODE         = 206,
-    AKEYCODE_CONTACTS        = 207,
-    AKEYCODE_CALENDAR        = 208,
-    AKEYCODE_MUSIC           = 209,
-    AKEYCODE_CALCULATOR      = 210,
-
-    // NOTE: If you add a new keycode here you must also add it to several other files.
-    //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _ANDROID_KEYCODES_H
diff --git a/native/include/android/looper.h b/native/include/android/looper.h
deleted file mode 100644
index 24e3967..0000000
--- a/native/include/android/looper.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_LOOPER_H
-#define ANDROID_LOOPER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * ALooper
- *
- * A looper is the state tracking an event loop for a thread.
- * Loopers do not define event structures or other such things; rather
- * they are a lower-level facility to attach one or more discrete objects
- * listening for an event.  An "event" here is simply data available on
- * a file descriptor: each attached object has an associated file descriptor,
- * and waiting for "events" means (internally) polling on all of these file
- * descriptors until one or more of them have data available.
- *
- * A thread can have only one ALooper associated with it.
- */
-struct ALooper;
-typedef struct ALooper ALooper;
-
-/**
- * Returns the looper associated with the calling thread, or NULL if
- * there is not one.
- */
-ALooper* ALooper_forThread();
-
-enum {
-    /**
-     * Option for ALooper_prepare: this looper will accept calls to
-     * ALooper_addFd() that do not have a callback (that is provide NULL
-     * for the callback).  In this case the caller of ALooper_pollOnce()
-     * or ALooper_pollAll() MUST check the return from these functions to
-     * discover when data is available on such fds and process it.
-     */
-    ALOOPER_PREPARE_ALLOW_NON_CALLBACKS = 1<<0
-};
-
-/**
- * Prepares a looper associated with the calling thread, and returns it.
- * If the thread already has a looper, it is returned.  Otherwise, a new
- * one is created, associated with the thread, and returned.
- *
- * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0.
- */
-ALooper* ALooper_prepare(int opts);
-
-enum {
-    /**
-     * Result from ALooper_pollOnce() and ALooper_pollAll():
-     * The poll was awoken using wake() before the timeout expired
-     * and no callbacks were executed and no other file descriptors were ready.
-     */
-    ALOOPER_POLL_WAKE = -1,
-
-    /**
-     * Result from ALooper_pollOnce() and ALooper_pollAll():
-     * One or more callbacks were executed.
-     */
-    ALOOPER_POLL_CALLBACK = -2,
-
-    /**
-     * Result from ALooper_pollOnce() and ALooper_pollAll():
-     * The timeout expired.
-     */
-    ALOOPER_POLL_TIMEOUT = -3,
-
-    /**
-     * Result from ALooper_pollOnce() and ALooper_pollAll():
-     * An error occurred.
-     */
-    ALOOPER_POLL_ERROR = -4,
-};
-
-/**
- * Acquire a reference on the given ALooper object.  This prevents the object
- * from being deleted until the reference is removed.  This is only needed
- * to safely hand an ALooper from one thread to another.
- */
-void ALooper_acquire(ALooper* looper);
-
-/**
- * Remove a reference that was previously acquired with ALooper_acquire().
- */
-void ALooper_release(ALooper* looper);
-
-/**
- * Flags for file descriptor events that a looper can monitor.
- *
- * These flag bits can be combined to monitor multiple events at once.
- */
-enum {
-    /**
-     * The file descriptor is available for read operations.
-     */
-    ALOOPER_EVENT_INPUT = 1 << 0,
-
-    /**
-     * The file descriptor is available for write operations.
-     */
-    ALOOPER_EVENT_OUTPUT = 1 << 1,
-
-    /**
-     * The file descriptor has encountered an error condition.
-     *
-     * The looper always sends notifications about errors; it is not necessary
-     * to specify this event flag in the requested event set.
-     */
-    ALOOPER_EVENT_ERROR = 1 << 2,
-
-    /**
-     * The file descriptor was hung up.
-     * For example, indicates that the remote end of a pipe or socket was closed.
-     *
-     * The looper always sends notifications about hangups; it is not necessary
-     * to specify this event flag in the requested event set.
-     */
-    ALOOPER_EVENT_HANGUP = 1 << 3,
-
-    /**
-     * The file descriptor is invalid.
-     * For example, the file descriptor was closed prematurely.
-     *
-     * The looper always sends notifications about invalid file descriptors; it is not necessary
-     * to specify this event flag in the requested event set.
-     */
-    ALOOPER_EVENT_INVALID = 1 << 4,
-};
-
-/**
- * For callback-based event loops, this is the prototype of the function
- * that is called when a file descriptor event occurs.
- * It is given the file descriptor it is associated with,
- * a bitmask of the poll events that were triggered (typically ALOOPER_EVENT_INPUT),
- * and the data pointer that was originally supplied.
- *
- * Implementations should return 1 to continue receiving callbacks, or 0
- * to have this file descriptor and callback unregistered from the looper.
- */
-typedef int (*ALooper_callbackFunc)(int fd, int events, void* data);
-
-/**
- * Waits for events to be available, with optional timeout in milliseconds.
- * Invokes callbacks for all file descriptors on which an event occurred.
- *
- * If the timeout is zero, returns immediately without blocking.
- * If the timeout is negative, waits indefinitely until an event appears.
- *
- * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
- * the timeout expired and no callbacks were invoked and no other file
- * descriptors were ready.
- *
- * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
- *
- * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
- * timeout expired.
- *
- * Returns ALOOPER_POLL_ERROR if an error occurred.
- *
- * Returns a value >= 0 containing an identifier if its file descriptor has data
- * and it has no callback function (requiring the caller here to handle it).
- * In this (and only this) case outFd, outEvents and outData will contain the poll
- * events and data associated with the fd, otherwise they will be set to NULL.
- *
- * This method does not return until it has finished invoking the appropriate callbacks
- * for all file descriptors that were signalled.
- */
-int ALooper_pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
-
-/**
- * Like ALooper_pollOnce(), but performs all pending callbacks until all
- * data has been consumed or a file descriptor is available with no callback.
- * This function will never return ALOOPER_POLL_CALLBACK.
- */
-int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData);
-
-/**
- * Wakes the poll asynchronously.
- *
- * This method can be called on any thread.
- * This method returns immediately.
- */
-void ALooper_wake(ALooper* looper);
-
-/**
- * Adds a new file descriptor to be polled by the looper.
- * If the same file descriptor was previously added, it is replaced.
- *
- * "fd" is the file descriptor to be added.
- * "ident" is an identifier for this event, which is returned from ALooper_pollOnce().
- * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback.
- * "events" are the poll events to wake up on.  Typically this is ALOOPER_EVENT_INPUT.
- * "callback" is the function to call when there is an event on the file descriptor.
- * "data" is a private data pointer to supply to the callback.
- *
- * There are two main uses of this function:
- *
- * (1) If "callback" is non-NULL, then this function will be called when there is
- * data on the file descriptor.  It should execute any events it has pending,
- * appropriately reading from the file descriptor.  The 'ident' is ignored in this case.
- *
- * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce
- * when its file descriptor has data available, requiring the caller to take
- * care of processing it.
- *
- * Returns 1 if the file descriptor was added or -1 if an error occurred.
- *
- * This method can be called on any thread.
- * This method may block briefly if it needs to wake the poll.
- */
-int ALooper_addFd(ALooper* looper, int fd, int ident, int events,
-        ALooper_callbackFunc callback, void* data);
-
-/**
- * Removes a previously added file descriptor from the looper.
- *
- * When this method returns, it is safe to close the file descriptor since the looper
- * will no longer have a reference to it.  However, it is possible for the callback to
- * already be running or for it to run one last time if the file descriptor was already
- * signalled.  Calling code is responsible for ensuring that this case is safely handled.
- * For example, if the callback takes care of removing itself during its own execution either
- * by returning 0 or by calling this method, then it can be guaranteed to not be invoked
- * again at any later time unless registered anew.
- *
- * Returns 1 if the file descriptor was removed, 0 if none was previously registered
- * or -1 if an error occurred.
- *
- * This method can be called on any thread.
- * This method may block briefly if it needs to wake the poll.
- */
-int ALooper_removeFd(ALooper* looper, int fd);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif // ANDROID_NATIVE_WINDOW_H
diff --git a/native/include/android/native_activity.h b/native/include/android/native_activity.h
deleted file mode 100644
index bc70f88..0000000
--- a/native/include/android/native_activity.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_NATIVE_ACTIVITY_H
-#define ANDROID_NATIVE_ACTIVITY_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <jni.h>
-
-#include <android/asset_manager.h>
-#include <android/input.h>
-#include <android/native_window.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ANativeActivityCallbacks;
-
-/**
- * This structure defines the native side of an android.app.NativeActivity.
- * It is created by the framework, and handed to the application's native
- * code as it is being launched.
- */
-typedef struct ANativeActivity {
-    /**
-     * Pointer to the callback function table of the native application.
-     * You can set the functions here to your own callbacks.  The callbacks
-     * pointer itself here should not be changed; it is allocated and managed
-     * for you by the framework.
-     */
-    struct ANativeActivityCallbacks* callbacks;
-
-    /**
-     * The global handle on the process's Java VM.
-     */
-    JavaVM* vm;
-
-    /**
-     * JNI context for the main thread of the app.  Note that this field
-     * can ONLY be used from the main thread of the process; that is, the
-     * thread that calls into the ANativeActivityCallbacks.
-     */
-    JNIEnv* env;
-
-    /**
-     * The NativeActivity object handle.
-     *
-     * IMPORTANT NOTE: This member is mis-named. It should really be named
-     * 'activity' instead of 'clazz', since it's a reference to the
-     * NativeActivity instance created by the system for you.
-     *
-     * We unfortunately cannot change this without breaking NDK
-     * source-compatibility.
-     */
-    jobject clazz;
-
-    /**
-     * Path to this application's internal data directory.
-     */
-    const char* internalDataPath;
-    
-    /**
-     * Path to this application's external (removable/mountable) data directory.
-     */
-    const char* externalDataPath;
-    
-    /**
-     * The platform's SDK version code.
-     */
-    int32_t sdkVersion;
-    
-    /**
-     * This is the native instance of the application.  It is not used by
-     * the framework, but can be set by the application to its own instance
-     * state.
-     */
-    void* instance;
-
-    /**
-     * Pointer to the Asset Manager instance for the application.  The application
-     * uses this to access binary assets bundled inside its own .apk file.
-     */
-    AAssetManager* assetManager;
-
-    /**
-     * Available starting with Honeycomb: path to the directory containing
-     * the application's OBB files (if any).  If the app doesn't have any
-     * OBB files, this directory may not exist.
-     */
-    const char* obbPath;
-} ANativeActivity;
-
-/**
- * These are the callbacks the framework makes into a native application.
- * All of these callbacks happen on the main thread of the application.
- * By default, all callbacks are NULL; set to a pointer to your own function
- * to have it called.
- */
-typedef struct ANativeActivityCallbacks {
-    /**
-     * NativeActivity has started.  See Java documentation for Activity.onStart()
-     * for more information.
-     */
-    void (*onStart)(ANativeActivity* activity);
-    
-    /**
-     * NativeActivity has resumed.  See Java documentation for Activity.onResume()
-     * for more information.
-     */
-    void (*onResume)(ANativeActivity* activity);
-    
-    /**
-     * Framework is asking NativeActivity to save its current instance state.
-     * See Java documentation for Activity.onSaveInstanceState() for more
-     * information.  The returned pointer needs to be created with malloc();
-     * the framework will call free() on it for you.  You also must fill in
-     * outSize with the number of bytes in the allocation.  Note that the
-     * saved state will be persisted, so it can not contain any active
-     * entities (pointers to memory, file descriptors, etc).
-     */
-    void* (*onSaveInstanceState)(ANativeActivity* activity, size_t* outSize);
-    
-    /**
-     * NativeActivity has paused.  See Java documentation for Activity.onPause()
-     * for more information.
-     */
-    void (*onPause)(ANativeActivity* activity);
-    
-    /**
-     * NativeActivity has stopped.  See Java documentation for Activity.onStop()
-     * for more information.
-     */
-    void (*onStop)(ANativeActivity* activity);
-    
-    /**
-     * NativeActivity is being destroyed.  See Java documentation for Activity.onDestroy()
-     * for more information.
-     */
-    void (*onDestroy)(ANativeActivity* activity);
-
-    /**
-     * Focus has changed in this NativeActivity's window.  This is often used,
-     * for example, to pause a game when it loses input focus.
-     */
-    void (*onWindowFocusChanged)(ANativeActivity* activity, int hasFocus);
-    
-    /**
-     * The drawing window for this native activity has been created.  You
-     * can use the given native window object to start drawing.
-     */
-    void (*onNativeWindowCreated)(ANativeActivity* activity, ANativeWindow* window);
-
-    /**
-     * The drawing window for this native activity has been resized.  You should
-     * retrieve the new size from the window and ensure that your rendering in
-     * it now matches.
-     */
-    void (*onNativeWindowResized)(ANativeActivity* activity, ANativeWindow* window);
-
-    /**
-     * The drawing window for this native activity needs to be redrawn.  To avoid
-     * transient artifacts during screen changes (such resizing after rotation),
-     * applications should not return from this function until they have finished
-     * drawing their window in its current state.
-     */
-    void (*onNativeWindowRedrawNeeded)(ANativeActivity* activity, ANativeWindow* window);
-
-    /**
-     * The drawing window for this native activity is going to be destroyed.
-     * You MUST ensure that you do not touch the window object after returning
-     * from this function: in the common case of drawing to the window from
-     * another thread, that means the implementation of this callback must
-     * properly synchronize with the other thread to stop its drawing before
-     * returning from here.
-     */
-    void (*onNativeWindowDestroyed)(ANativeActivity* activity, ANativeWindow* window);
-    
-    /**
-     * The input queue for this native activity's window has been created.
-     * You can use the given input queue to start retrieving input events.
-     */
-    void (*onInputQueueCreated)(ANativeActivity* activity, AInputQueue* queue);
-    
-    /**
-     * The input queue for this native activity's window is being destroyed.
-     * You should no longer try to reference this object upon returning from this
-     * function.
-     */
-    void (*onInputQueueDestroyed)(ANativeActivity* activity, AInputQueue* queue);
-
-    /**
-     * The rectangle in the window in which content should be placed has changed.
-     */
-    void (*onContentRectChanged)(ANativeActivity* activity, const ARect* rect);
-
-    /**
-     * The current device AConfiguration has changed.  The new configuration can
-     * be retrieved from assetManager.
-     */
-    void (*onConfigurationChanged)(ANativeActivity* activity);
-
-    /**
-     * The system is running low on memory.  Use this callback to release
-     * resources you do not need, to help the system avoid killing more
-     * important processes.
-     */
-    void (*onLowMemory)(ANativeActivity* activity);
-} ANativeActivityCallbacks;
-
-/**
- * This is the function that must be in the native code to instantiate the
- * application's native activity.  It is called with the activity instance (see
- * above); if the code is being instantiated from a previously saved instance,
- * the savedState will be non-NULL and point to the saved data.  You must make
- * any copy of this data you need -- it will be released after you return from
- * this function.
- */
-typedef void ANativeActivity_createFunc(ANativeActivity* activity,
-        void* savedState, size_t savedStateSize);
-
-/**
- * The name of the function that NativeInstance looks for when launching its
- * native code.  This is the default function that is used, you can specify
- * "android.app.func_name" string meta-data in your manifest to use a different
- * function.
- */
-extern ANativeActivity_createFunc ANativeActivity_onCreate;
-
-/**
- * Finish the given activity.  Its finish() method will be called, causing it
- * to be stopped and destroyed.  Note that this method can be called from
- * *any* thread; it will send a message to the main thread of the process
- * where the Java finish call will take place.
- */
-void ANativeActivity_finish(ANativeActivity* activity);
-
-/**
- * Change the window format of the given activity.  Calls getWindow().setFormat()
- * of the given activity.  Note that this method can be called from
- * *any* thread; it will send a message to the main thread of the process
- * where the Java finish call will take place.
- */
-void ANativeActivity_setWindowFormat(ANativeActivity* activity, int32_t format);
-
-/**
- * Change the window flags of the given activity.  Calls getWindow().setFlags()
- * of the given activity.  Note that this method can be called from
- * *any* thread; it will send a message to the main thread of the process
- * where the Java finish call will take place.  See window.h for flag constants.
- */
-void ANativeActivity_setWindowFlags(ANativeActivity* activity,
-        uint32_t addFlags, uint32_t removeFlags);
-
-/**
- * Flags for ANativeActivity_showSoftInput; see the Java InputMethodManager
- * API for documentation.
- */
-enum {
-    ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT = 0x0001,
-    ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED = 0x0002,
-};
-
-/**
- * Show the IME while in the given activity.  Calls InputMethodManager.showSoftInput()
- * for the given activity.  Note that this method can be called from
- * *any* thread; it will send a message to the main thread of the process
- * where the Java finish call will take place.
- */
-void ANativeActivity_showSoftInput(ANativeActivity* activity, uint32_t flags);
-
-/**
- * Flags for ANativeActivity_hideSoftInput; see the Java InputMethodManager
- * API for documentation.
- */
-enum {
-    ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY = 0x0001,
-    ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS = 0x0002,
-};
-
-/**
- * Hide the IME while in the given activity.  Calls InputMethodManager.hideSoftInput()
- * for the given activity.  Note that this method can be called from
- * *any* thread; it will send a message to the main thread of the process
- * where the Java finish call will take place.
- */
-void ANativeActivity_hideSoftInput(ANativeActivity* activity, uint32_t flags);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif // ANDROID_NATIVE_ACTIVITY_H
-
diff --git a/native/include/android/native_window.h b/native/include/android/native_window.h
deleted file mode 100644
index 2f4f2d3..0000000
--- a/native/include/android/native_window.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_NATIVE_WINDOW_H
-#define ANDROID_NATIVE_WINDOW_H
-
-#include <android/rect.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Pixel formats that a window can use.
- */
-enum {
-    WINDOW_FORMAT_RGBA_8888          = 1,
-    WINDOW_FORMAT_RGBX_8888          = 2,
-    WINDOW_FORMAT_RGB_565            = 4,
-};
-
-struct ANativeWindow;
-typedef struct ANativeWindow ANativeWindow;
-
-typedef struct ANativeWindow_Buffer {
-    // The number of pixels that are show horizontally.
-    int32_t width;
-
-    // The number of pixels that are shown vertically.
-    int32_t height;
-
-    // The number of *pixels* that a line in the buffer takes in
-    // memory.  This may be >= width.
-    int32_t stride;
-
-    // The format of the buffer.  One of WINDOW_FORMAT_*
-    int32_t format;
-
-    // The actual bits.
-    void* bits;
-    
-    // Do not touch.
-    uint32_t reserved[6];
-} ANativeWindow_Buffer;
-
-/**
- * Acquire a reference on the given ANativeWindow object.  This prevents the object
- * from being deleted until the reference is removed.
- */
-void ANativeWindow_acquire(ANativeWindow* window);
-
-/**
- * Remove a reference that was previously acquired with ANativeWindow_acquire().
- */
-void ANativeWindow_release(ANativeWindow* window);
-
-/*
- * Return the current width in pixels of the window surface.  Returns a
- * negative value on error.
- */
-int32_t ANativeWindow_getWidth(ANativeWindow* window);
-
-/*
- * Return the current height in pixels of the window surface.  Returns a
- * negative value on error.
- */
-int32_t ANativeWindow_getHeight(ANativeWindow* window);
-
-/*
- * Return the current pixel format of the window surface.  Returns a
- * negative value on error.
- */
-int32_t ANativeWindow_getFormat(ANativeWindow* window);
-
-/*
- * Change the format and size of the window buffers.
- *
- * The width and height control the number of pixels in the buffers, not the
- * dimensions of the window on screen.  If these are different than the
- * window's physical size, then it buffer will be scaled to match that size
- * when compositing it to the screen.
- *
- * For all of these parameters, if 0 is supplied then the window's base
- * value will come back in force.
- *
- * width and height must be either both zero or both non-zero.
- *
- */
-int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
-        int32_t width, int32_t height, int32_t format);
-
-/**
- * Lock the window's next drawing surface for writing.
- * inOutDirtyBounds is used as an in/out parameter, upon entering the
- * function, it contains the dirty region, that is, the region the caller
- * intends to redraw. When the function returns, inOutDirtyBounds is updated
- * with the actual area the caller needs to redraw -- this region is often
- * extended by ANativeWindow_lock.
- */
-int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
-        ARect* inOutDirtyBounds);
-
-/**
- * Unlock the window's drawing surface after previously locking it,
- * posting the new buffer to the display.
- */
-int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif // ANDROID_NATIVE_WINDOW_H
diff --git a/native/include/android/native_window_jni.h b/native/include/android/native_window_jni.h
deleted file mode 100644
index b9e72ef..0000000
--- a/native/include/android/native_window_jni.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_NATIVE_WINDOW_JNI_H
-#define ANDROID_NATIVE_WINDOW_JNI_H
-
-#include <android/native_window.h>
-
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Return the ANativeWindow associated with a Java Surface object,
- * for interacting with it through native code.  This acquires a reference
- * on the ANativeWindow that is returned; be sure to use ANativeWindow_release()
- * when done with it so that it doesn't leak.
- */
-ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif // ANDROID_NATIVE_WINDOW_H
diff --git a/native/include/android/obb.h b/native/include/android/obb.h
deleted file mode 100644
index 65e9b2a..0000000
--- a/native/include/android/obb.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_OBB_H
-#define ANDROID_OBB_H
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct AObbInfo;
-typedef struct AObbInfo AObbInfo;
-
-enum {
-    AOBBINFO_OVERLAY = 0x0001,
-};
-
-/**
- * Scan an OBB and get information about it.
- */
-AObbInfo* AObbScanner_getObbInfo(const char* filename);
-
-/**
- * Destroy the AObbInfo object. You must call this when finished with the object.
- */
-void AObbInfo_delete(AObbInfo* obbInfo);
-
-/**
- * Get the package name for the OBB.
- */
-const char* AObbInfo_getPackageName(AObbInfo* obbInfo);
-
-/**
- * Get the version of an OBB file.
- */
-int32_t AObbInfo_getVersion(AObbInfo* obbInfo);
-
-/**
- * Get the flags of an OBB file.
- */
-int32_t AObbInfo_getFlags(AObbInfo* obbInfo);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif      // ANDROID_OBB_H
diff --git a/native/include/android/rect.h b/native/include/android/rect.h
deleted file mode 100644
index 64d487d..0000000
--- a/native/include/android/rect.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_RECT_H
-#define ANDROID_RECT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct ARect {
-#ifdef __cplusplus
-    typedef int32_t value_type;
-#endif
-    int32_t left;
-    int32_t top;
-    int32_t right;
-    int32_t bottom;
-} ARect;
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif // ANDROID_RECT_H
diff --git a/native/include/android/sensor.h b/native/include/android/sensor.h
deleted file mode 100644
index f163f18..0000000
--- a/native/include/android/sensor.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_SENSOR_H
-#define ANDROID_SENSOR_H
-
-/******************************************************************
- *
- * IMPORTANT NOTICE:
- *
- *   This file is part of Android's set of stable system headers
- *   exposed by the Android NDK (Native Development Kit).
- *
- *   Third-party source AND binary code relies on the definitions
- *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
- *
- *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
- *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
- *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
- *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
- */
-
-/*
- * Structures and functions to receive and process sensor events in
- * native code.
- *
- */
-
-#include <sys/types.h>
-
-#include <android/looper.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*
- * Sensor types
- * (keep in sync with hardware/sensor.h)
- */
-
-enum {
-    ASENSOR_TYPE_ACCELEROMETER      = 1,
-    ASENSOR_TYPE_MAGNETIC_FIELD     = 2,
-    ASENSOR_TYPE_GYROSCOPE          = 4,
-    ASENSOR_TYPE_LIGHT              = 5,
-    ASENSOR_TYPE_PROXIMITY          = 8
-};
-
-/*
- * Sensor accuracy measure
- */
-enum {
-    ASENSOR_STATUS_UNRELIABLE       = 0,
-    ASENSOR_STATUS_ACCURACY_LOW     = 1,
-    ASENSOR_STATUS_ACCURACY_MEDIUM  = 2,
-    ASENSOR_STATUS_ACCURACY_HIGH    = 3
-};
-
-/*
- * A few useful constants
- */
-
-/* Earth's gravity in m/s^2 */
-#define ASENSOR_STANDARD_GRAVITY            (9.80665f)
-/* Maximum magnetic field on Earth's surface in uT */
-#define ASENSOR_MAGNETIC_FIELD_EARTH_MAX    (60.0f)
-/* Minimum magnetic field on Earth's surface in uT*/
-#define ASENSOR_MAGNETIC_FIELD_EARTH_MIN    (30.0f)
-
-/*
- * A sensor event.
- */
-
-/* NOTE: Must match hardware/sensors.h */
-typedef struct ASensorVector {
-    union {
-        float v[3];
-        struct {
-            float x;
-            float y;
-            float z;
-        };
-        struct {
-            float azimuth;
-            float pitch;
-            float roll;
-        };
-    };
-    int8_t status;
-    uint8_t reserved[3];
-} ASensorVector;
-
-/* NOTE: Must match hardware/sensors.h */
-typedef struct ASensorEvent {
-    int32_t version; /* sizeof(struct ASensorEvent) */
-    int32_t sensor;
-    int32_t type;
-    int32_t reserved0;
-    int64_t timestamp;
-    union {
-        float           data[16];
-        ASensorVector   vector;
-        ASensorVector   acceleration;
-        ASensorVector   magnetic;
-        float           temperature;
-        float           distance;
-        float           light;
-        float           pressure;
-    };
-    int32_t reserved1[4];
-} ASensorEvent;
-
-
-struct ASensorManager;
-typedef struct ASensorManager ASensorManager;
-
-struct ASensorEventQueue;
-typedef struct ASensorEventQueue ASensorEventQueue;
-
-struct ASensor;
-typedef struct ASensor ASensor;
-typedef ASensor const* ASensorRef;
-typedef ASensorRef const* ASensorList;
-
-/*****************************************************************************/
-
-/*
- * Get a reference to the sensor manager. ASensorManager is a singleton.
- *
- * Example:
- *
- *     ASensorManager* sensorManager = ASensorManager_getInstance();
- *
- */
-ASensorManager* ASensorManager_getInstance();
-
-
-/*
- * Returns the list of available sensors.
- */
-int ASensorManager_getSensorList(ASensorManager* manager, ASensorList* list);
-
-/*
- * Returns the default sensor for the given type, or NULL if no sensor
- * of that type exist.
- */
-ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
-
-/*
- * Creates a new sensor event queue and associate it with a looper.
- */
-ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager,
-        ALooper* looper, int ident, ALooper_callbackFunc callback, void* data);
-
-/*
- * Destroys the event queue and free all resources associated to it.
- */
-int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
-
-
-/*****************************************************************************/
-
-/*
- * Enable the selected sensor. Returns a negative error code on failure.
- */
-int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor);
-
-/*
- * Disable the selected sensor. Returns a negative error code on failure.
- */
-int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor const* sensor);
-
-/*
- * Sets the delivery rate of events in microseconds for the given sensor.
- * Note that this is a hint only, generally event will arrive at a higher
- * rate. It is an error to set a rate inferior to the value returned by
- * ASensor_getMinDelay().
- * Returns a negative error code on failure.
- */
-int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor const* sensor, int32_t usec);
-
-/*
- * Returns true if there are one or more events available in the
- * sensor queue.  Returns 1 if the queue has events; 0 if
- * it does not have events; and a negative value if there is an error.
- */
-int ASensorEventQueue_hasEvents(ASensorEventQueue* queue);
-
-/*
- * Returns the next available events from the queue.  Returns a negative
- * value if no events are available or an error has occurred, otherwise
- * the number of events returned.
- *
- * Examples:
- *   ASensorEvent event;
- *   ssize_t numEvent = ASensorEventQueue_getEvents(queue, &event, 1);
- *
- *   ASensorEvent eventBuffer[8];
- *   ssize_t numEvent = ASensorEventQueue_getEvents(queue, eventBuffer, 8);
- *
- */
-ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue,
-                ASensorEvent* events, size_t count);
-
-
-/*****************************************************************************/
-
-/*
- * Returns this sensor's name (non localized)
- */
-const char* ASensor_getName(ASensor const* sensor);
-
-/*
- * Returns this sensor's vendor's name (non localized)
- */
-const char* ASensor_getVendor(ASensor const* sensor);
-
-/*
- * Return this sensor's type
- */
-int ASensor_getType(ASensor const* sensor);
-
-/*
- * Returns this sensors's resolution
- */
-float ASensor_getResolution(ASensor const* sensor);
-
-/*
- * Returns the minimum delay allowed between events in microseconds.
- * A value of zero means that this sensor doesn't report events at a
- * constant rate, but rather only when a new data is available.
- */
-int ASensor_getMinDelay(ASensor const* sensor);
-
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif // ANDROID_SENSOR_H
diff --git a/native/include/android/storage_manager.h b/native/include/android/storage_manager.h
deleted file mode 100644
index bad24913..0000000
--- a/native/include/android/storage_manager.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_STORAGE_MANAGER_H
-#define ANDROID_STORAGE_MANAGER_H
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct AStorageManager;
-typedef struct AStorageManager AStorageManager;
-
-enum {
-    /*
-     * The OBB container is now mounted and ready for use. Can be returned
-     * as the status for callbacks made during asynchronous OBB actions.
-     */
-    AOBB_STATE_MOUNTED = 1,
-
-    /*
-     * The OBB container is now unmounted and not usable. Can be returned
-     * as the status for callbacks made during asynchronous OBB actions.
-     */
-    AOBB_STATE_UNMOUNTED = 2,
-
-    /*
-     * There was an internal system error encountered while trying to
-     * mount the OBB. Can be returned as the status for callbacks made
-     * during asynchronous OBB actions.
-     */
-    AOBB_STATE_ERROR_INTERNAL = 20,
-
-    /*
-     * The OBB could not be mounted by the system. Can be returned as the
-     * status for callbacks made during asynchronous OBB actions.
-     */
-    AOBB_STATE_ERROR_COULD_NOT_MOUNT = 21,
-
-    /*
-     * The OBB could not be unmounted. This most likely indicates that a
-     * file is in use on the OBB. Can be returned as the status for
-     * callbacks made during asynchronous OBB actions.
-     */
-    AOBB_STATE_ERROR_COULD_NOT_UNMOUNT = 22,
-
-    /*
-     * A call was made to unmount the OBB when it was not mounted. Can be
-     * returned as the status for callbacks made during asynchronous OBB
-     * actions.
-     */
-    AOBB_STATE_ERROR_NOT_MOUNTED = 23,
-
-    /*
-     * The OBB has already been mounted. Can be returned as the status for
-     * callbacks made during asynchronous OBB actions.
-     */
-    AOBB_STATE_ERROR_ALREADY_MOUNTED = 24,
-
-    /*
-     * The current application does not have permission to use this OBB.
-     * This could be because the OBB indicates it's owned by a different
-     * package. Can be returned as the status for callbacks made during
-     * asynchronous OBB actions.
-     */
-    AOBB_STATE_ERROR_PERMISSION_DENIED = 25,
-};
-
-/**
- * Obtains a new instance of AStorageManager.
- */
-AStorageManager* AStorageManager_new();
-
-/**
- * Release AStorageManager instance.
- */
-void AStorageManager_delete(AStorageManager* mgr);
-
-/**
- * Callback function for asynchronous calls made on OBB files.
- */
-typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const int32_t state, void* data);
-
-/**
- * Attempts to mount an OBB file. This is an asynchronous operation.
- */
-void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key,
-        AStorageManager_obbCallbackFunc cb, void* data);
-
-/**
- * Attempts to unmount an OBB file. This is an asynchronous operation.
- */
-void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force,
-        AStorageManager_obbCallbackFunc cb, void* data);
-
-/**
- * Check whether an OBB is mounted.
- */
-int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename);
-
-/**
- * Get the mounted path for an OBB.
- */
-const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename);
-
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif      // ANDROID_STORAGE_MANAGER_H
diff --git a/native/include/android/window.h b/native/include/android/window.h
deleted file mode 100644
index 2ab192b..0000000
--- a/native/include/android/window.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-
-#ifndef ANDROID_WINDOW_H
-#define ANDROID_WINDOW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Window flags, as per the Java API at android.view.WindowManager.LayoutParams.
- */
-enum {
-    AWINDOW_FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
-    AWINDOW_FLAG_DIM_BEHIND                 = 0x00000002,
-    AWINDOW_FLAG_BLUR_BEHIND                = 0x00000004,
-    AWINDOW_FLAG_NOT_FOCUSABLE              = 0x00000008,
-    AWINDOW_FLAG_NOT_TOUCHABLE              = 0x00000010,
-    AWINDOW_FLAG_NOT_TOUCH_MODAL            = 0x00000020,
-    AWINDOW_FLAG_TOUCHABLE_WHEN_WAKING      = 0x00000040,
-    AWINDOW_FLAG_KEEP_SCREEN_ON             = 0x00000080,
-    AWINDOW_FLAG_LAYOUT_IN_SCREEN           = 0x00000100,
-    AWINDOW_FLAG_LAYOUT_NO_LIMITS           = 0x00000200,
-    AWINDOW_FLAG_FULLSCREEN                 = 0x00000400,
-    AWINDOW_FLAG_FORCE_NOT_FULLSCREEN       = 0x00000800,
-    AWINDOW_FLAG_DITHER                     = 0x00001000,
-    AWINDOW_FLAG_SECURE                     = 0x00002000,
-    AWINDOW_FLAG_SCALED                     = 0x00004000,
-    AWINDOW_FLAG_IGNORE_CHEEK_PRESSES       = 0x00008000,
-    AWINDOW_FLAG_LAYOUT_INSET_DECOR         = 0x00010000,
-    AWINDOW_FLAG_ALT_FOCUSABLE_IM           = 0x00020000,
-    AWINDOW_FLAG_WATCH_OUTSIDE_TOUCH        = 0x00040000,
-    AWINDOW_FLAG_SHOW_WHEN_LOCKED           = 0x00080000,
-    AWINDOW_FLAG_SHOW_WALLPAPER             = 0x00100000,
-    AWINDOW_FLAG_TURN_SCREEN_ON             = 0x00200000,
-    AWINDOW_FLAG_DISMISS_KEYGUARD           = 0x00400000,
-};
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif // ANDROID_WINDOW_H
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 090c0cb7..07f9e91 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -23,6 +23,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.os.Build;
+import android.os.UserId;
 import android.util.Log;
 
 import java.nio.Buffer;
@@ -67,7 +68,7 @@
         int version = 0;
         IPackageManager pm = AppGlobals.getPackageManager();
         try {
-            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
+            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0, UserId.myUserId());
             if (applicationInfo != null) {
                 version = applicationInfo.targetSdkVersion;
             }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 330a189..abf713b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -84,6 +84,7 @@
     public DatabaseHelper(Context context) {
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
         mContext = context;
+        setWriteAheadLoggingEnabled(true);
     }
 
     public static boolean isValidTable(String name) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 95fd62d..1fa3695 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -260,7 +260,6 @@
         // Watch for external modifications to the database file,
         // keeping our cache in sync.
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        db.enableWriteAheadLogging();
         sObserverInstance = new SettingsFileObserver(db.getPath());
         sObserverInstance.startWatching();
         startAsyncCachePopulation();
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4d9b2cd..0f48f35 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -65,7 +65,7 @@
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"Probíhá ukládání snímku obrazovky."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky byl zachycen."</string>
+    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky zachycen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Snímek obrazovky zobrazíte dotykem."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"Snímek obrazovky se nepodařilo uložit. Je možné, že je externí úložiště právě používáno."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7e0e3c4..1f9c959 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -24,12 +24,12 @@
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"请勿打扰"</string>
     <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_accessibility_dismiss_recents" msgid="4576076075226540105">"关闭最近运行的应用程序"</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_accessibility_dismiss_recents" msgid="4576076075226540105">"关闭最近运行的应用"</string>
   <plurals name="status_bar_accessibility_recent_apps">
-    <item quantity="one" msgid="5854176083865845541">"1 个最近运行的应用程序"</item>
-    <item quantity="other" msgid="1040784359794890744">"%d 个最近运行的应用程序"</item>
+    <item quantity="one" msgid="5854176083865845541">"1 个最近运行的应用"</item>
+    <item quantity="other" msgid="1040784359794890744">"%d 个最近运行的应用"</item>
   </plurals>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"无通知"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string>
@@ -49,11 +49,11 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"已通过蓝牙共享网络"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"设置输入法"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"使用物理键盘"</string>
-    <string name="usb_device_permission_prompt" msgid="834698001271562057">"允许应用程序“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该 USB 设备吗?"</string>
-    <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"允许应用程序“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该 USB 配件吗?"</string>
+    <string name="usb_device_permission_prompt" msgid="834698001271562057">"允许应用“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该 USB 设备吗?"</string>
+    <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"允许应用“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该 USB 配件吗?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"要在连接此 USB 设备时打开<xliff:g id="ACTIVITY">%1$s</xliff:g>吗?"</string>
     <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"要在连接此 USB 配件时打开<xliff:g id="ACTIVITY">%1$s</xliff:g>吗?"</string>
-    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"未安装此 USB 配件适用的应用程序。要了解此配件的详情,请访问:<xliff:g id="URL">%1$s</xliff:g>"</string>
+    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"未安装此 USB 配件适用的应用。要了解此配件的详情,请访问:<xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB 配件"</string>
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该 USB 设备"</string>
@@ -61,7 +61,7 @@
     <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>
-    <string name="compat_mode_help_body" msgid="4946726776359270040">"如果应用程序是针对较小屏幕设计的,则时钟旁会显示缩放控件。"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"如果应用是针对较小屏幕设计的,则时钟旁会显示缩放控件。"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在保存屏幕截图..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"正在保存屏幕截图..."</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"正在保存屏幕截图。"</string>
@@ -72,11 +72,11 @@
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 文件传输选项"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器 (MTP) 装载"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"作为摄像头 (PTP) 装载"</string>
-    <string name="installer_cd_button_title" msgid="2312667578562201583">"安装适用于苹果机的“Android 文件传输”应用程序"</string>
+    <string name="installer_cd_button_title" msgid="2312667578562201583">"安装适用于苹果机的“Android 文件传输”应用"</string>
     <string name="accessibility_back" msgid="567011538994429120">"返回"</string>
     <string name="accessibility_home" msgid="8217216074895377641">"主屏幕"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"菜单"</string>
-    <string name="accessibility_recent" msgid="8571350598987952883">"最近运行的应用程序"</string>
+    <string name="accessibility_recent" msgid="8571350598987952883">"最近运行的应用"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"输入法切换按钮。"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"兼容性缩放按钮。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"将小屏幕的图片放大在较大屏幕上显示。"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 66cb32c..564b07b 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.LayoutTransition;
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -615,10 +616,11 @@
         if (!mFirstScreenful && tasks.size() == 0) {
             return;
         }
-        mNumItemsWaitingForThumbnailsAndIcons =
-                mFirstScreenful ? tasks.size() : mRecentTaskDescriptions.size();
+        mNumItemsWaitingForThumbnailsAndIcons = mFirstScreenful 
+                ? tasks.size() : mRecentTaskDescriptions == null 
+                        ? 0 : mRecentTaskDescriptions.size();
         if (mRecentTaskDescriptions == null) {
-            mRecentTaskDescriptions = new ArrayList(tasks);
+            mRecentTaskDescriptions = new ArrayList<TaskDescription>(tasks);
         } else {
             mRecentTaskDescriptions.addAll(tasks);
         }
@@ -656,22 +658,33 @@
     }
 
     public void handleOnClick(View view) {
-        TaskDescription ad = ((ViewHolder) view.getTag()).taskDescription;
+        ViewHolder holder = (ViewHolder)view.getTag();
+        TaskDescription ad = holder.taskDescription;
         final Context context = view.getContext();
         final ActivityManager am = (ActivityManager)
                 context.getSystemService(Context.ACTIVITY_SERVICE);
+        holder.thumbnailViewImage.setDrawingCacheEnabled(true);
+        Bitmap bm = holder.thumbnailViewImage.getDrawingCache();
+        ActivityOptions opts = ActivityOptions.makeThumbnailScaleUpAnimation(
+                holder.thumbnailViewImage, bm, 0, 0,
+                new ActivityOptions.OnAnimationStartedListener() {
+                    @Override public void onAnimationStarted() {
+                        hide(true);
+                    }
+                });
         if (ad.taskId >= 0) {
             // This is an active task; it should just go to the foreground.
-            am.moveTaskToFront(ad.taskId, ActivityManager.MOVE_TASK_WITH_HOME);
+            am.moveTaskToFront(ad.taskId, ActivityManager.MOVE_TASK_WITH_HOME,
+                    opts.toBundle());
         } else {
             Intent intent = ad.intent;
             intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
                     | Intent.FLAG_ACTIVITY_TASK_ON_HOME
                     | Intent.FLAG_ACTIVITY_NEW_TASK);
             if (DEBUG) Log.v(TAG, "Starting activity " + intent);
-            context.startActivity(intent);
+            context.startActivity(intent, opts.toBundle());
         }
-        hide(true);
+        holder.thumbnailViewImage.setDrawingCacheEnabled(false);
     }
 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
diff --git a/packages/VpnDialogs/res/values-zh-rCN/strings.xml b/packages/VpnDialogs/res/values-zh-rCN/strings.xml
index 7fdb368..ed844ad 100644
--- a/packages/VpnDialogs/res/values-zh-rCN/strings.xml
+++ b/packages/VpnDialogs/res/values-zh-rCN/strings.xml
@@ -17,8 +17,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="8359175999006833462">"“<xliff:g id="APP">%s</xliff:g>”尝试创建 VPN 连接。"</string>
-    <string name="warning" msgid="5470743576660160079">"继续操作即表示您授予此应用程序拦截所有网络流量的权限。"<b>"除非您信任此应用程序,否则请勿接受此请求。"</b>"如果您在不信任该应用程序的情况下接受了此请求,则可能会面临数据遭到恶意软件盗用的风险。"</string>
-    <string name="accept" msgid="2889226408765810173">"我信任此应用程序。"</string>
+    <string name="warning" msgid="5470743576660160079">"继续操作即表示您授予此应用拦截所有网络流量的权限。"<b>"除非您信任此应用,否则请勿接受此请求。"</b>"如果您在不信任该应用的情况下接受了此请求,则可能会面临数据遭到恶意软件盗用的风险。"</string>
+    <string name="accept" msgid="2889226408765810173">"我信任此应用。"</string>
     <string name="legacy_title" msgid="192936250066580964">"已连接 VPN"</string>
     <string name="configure" msgid="4905518375574791375">"配置"</string>
     <string name="disconnect" msgid="971412338304200056">"断开连接"</string>
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index a1f7316..b5dace0 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -463,6 +463,7 @@
     // Screenshot trigger states
     // Time to volume and power must be pressed within this interval of each other.
     private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
+    private boolean mScreenshotChordEnabled;
     private boolean mVolumeDownKeyTriggered;
     private long mVolumeDownKeyTime;
     private boolean mVolumeDownKeyConsumedByScreenshotChord;
@@ -636,7 +637,8 @@
     }
 
     private void interceptScreenshotChord() {
-        if (mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
+        if (mScreenshotChordEnabled
+                && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
             final long now = SystemClock.uptimeMillis();
             if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
                     && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
@@ -882,6 +884,9 @@
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
 
+        mScreenshotChordEnabled = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableScreenshotChord);
+
         // Controls rotation and the like.
         initializeHdmiState();
 
@@ -1574,7 +1579,7 @@
         // If we think we might have a volume down & power key chord on the way
         // but we're not sure, then tell the dispatcher to wait a little while and
         // try again later before dispatching.
-        if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
+        if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
             if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
                 final long now = SystemClock.uptimeMillis();
                 final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 081f1f4..a85b605 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -325,9 +325,10 @@
                     service.onConfigurationChanged();
                 }
             } else {
-                // TODO: Verify that this only needs to be delivered for the related user and not
-                // all the users
-                getImplForUser().onBroadcastReceived(intent);
+                for (int i = 0; i < mAppWidgetServices.size(); i++) {
+                    AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
+                    service.onBroadcastReceived(intent);
+                }
             }
         }
     };
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 9c408c4..182a884 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.app.AlarmManager;
+import android.app.AppGlobals;
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
@@ -27,6 +28,7 @@
 import android.content.Intent.FilterComparison;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -158,7 +160,7 @@
 
     Context mContext;
     Locale mLocale;
-    PackageManager mPackageManager;
+    IPackageManager mPm;
     AlarmManager mAlarmManager;
     ArrayList<Provider> mInstalledProviders = new ArrayList<Provider>();
     int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1;
@@ -174,7 +176,7 @@
 
     AppWidgetServiceImpl(Context context, int userId) {
         mContext = context;
-        mPackageManager = context.getPackageManager();
+        mPm = AppGlobals.getPackageManager();
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         mUserId = userId;
     }
@@ -1009,16 +1011,19 @@
     }
 
     void loadAppWidgetList() {
-        PackageManager pm = mPackageManager;
-
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
-        List<ResolveInfo> broadcastReceivers = pm.queryBroadcastReceivers(intent,
-                PackageManager.GET_META_DATA);
+        try {
+            List<ResolveInfo> broadcastReceivers = mPm.queryIntentReceivers(intent,
+                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                    PackageManager.GET_META_DATA, mUserId);
 
-        final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
-        for (int i = 0; i < N; i++) {
-            ResolveInfo ri = broadcastReceivers.get(i);
-            addProviderLocked(ri);
+            final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
+            for (int i = 0; i < N; i++) {
+                ResolveInfo ri = broadcastReceivers.get(i);
+                addProviderLocked(ri);
+            }
+        } catch (RemoteException re) {
+            // Shouldn't happen, local call
         }
     }
 
@@ -1131,7 +1136,7 @@
         ActivityInfo activityInfo = ri.activityInfo;
         XmlResourceParser parser = null;
         try {
-            parser = activityInfo.loadXmlMetaData(mPackageManager,
+            parser = activityInfo.loadXmlMetaData(mContext.getPackageManager(),
                     AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
             if (parser == null) {
                 Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER
@@ -1159,7 +1164,7 @@
             info.provider = component;
             p.uid = activityInfo.applicationInfo.uid;
 
-            Resources res = mPackageManager
+            Resources res = mContext.getPackageManager()
                     .getResourcesForApplication(activityInfo.applicationInfo);
 
             TypedArray sa = res.obtainAttributes(attrs,
@@ -1188,7 +1193,7 @@
             if (className != null) {
                 info.configure = new ComponentName(component.getPackageName(), className);
             }
-            info.label = activityInfo.loadLabel(mPackageManager).toString();
+            info.label = activityInfo.loadLabel(mContext.getPackageManager()).toString();
             info.icon = ri.getIconResource();
             info.previewImage = sa.getResourceId(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
@@ -1213,7 +1218,12 @@
     }
 
     int getUidForPackage(String packageName) throws PackageManager.NameNotFoundException {
-        PackageInfo pkgInfo = mPackageManager.getPackageInfo(packageName, 0);
+        PackageInfo pkgInfo = null;
+        try {
+            pkgInfo = mPm.getPackageInfo(packageName, 0, mUserId);
+        } catch (RemoteException re) {
+            // Shouldn't happen, local call
+        }
         if (pkgInfo == null || pkgInfo.applicationInfo == null) {
             throw new PackageManager.NameNotFoundException();
         }
@@ -1493,9 +1503,15 @@
     void addProvidersForPackageLocked(String pkgName) {
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
         intent.setPackage(pkgName);
-        List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
-                PackageManager.GET_META_DATA);
-
+        List<ResolveInfo> broadcastReceivers;
+        try {
+            broadcastReceivers = mPm.queryIntentReceivers(intent,
+                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                    PackageManager.GET_META_DATA, mUserId);
+        } catch (RemoteException re) {
+            // Shouldn't happen, local call
+            return;
+        }
         final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
         for (int i = 0; i < N; i++) {
             ResolveInfo ri = broadcastReceivers.get(i);
@@ -1513,8 +1529,15 @@
         HashSet<String> keep = new HashSet<String>();
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
         intent.setPackage(pkgName);
-        List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
-                PackageManager.GET_META_DATA);
+        List<ResolveInfo> broadcastReceivers;
+        try {
+            broadcastReceivers = mPm.queryIntentReceivers(intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                PackageManager.GET_META_DATA, mUserId);
+        } catch (RemoteException re) {
+            // Shouldn't happen, local call
+            return;
+        }
 
         // add the missing ones and collect which ones to keep
         int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index a7b08f5..bd12270 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -1986,6 +1986,16 @@
             try {
                 mCurrentPackage = mPackageManager.getPackageInfo(request.packageName,
                         PackageManager.GET_SIGNATURES);
+                if (mCurrentPackage.applicationInfo.backupAgentName == null) {
+                    // The manifest has changed but we had a stale backup request pending.
+                    // This won't happen again because the app won't be requesting further
+                    // backups.
+                    Slog.i(TAG, "Package " + request.packageName
+                            + " no longer supports backup; skipping");
+                    addBackupTrace("skipping - no agent, completion is noop");
+                    executeNextState(BackupState.RUNNING_QUEUE);
+                    return;
+                }
 
                 IBackupAgent agent = null;
                 try {
@@ -2547,6 +2557,8 @@
                 finalizeBackup(out);
             } catch (RemoteException e) {
                 Slog.e(TAG, "App died during full backup");
+            } catch (Exception e) {
+                Slog.e(TAG, "Internal exception during full backup", e);
             } finally {
                 tearDown(pkg);
                 try {
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index b3d7220..f7e841e 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -201,7 +201,7 @@
     }
 
     public List<R> queryIntentFromList(Intent intent, String resolvedType, 
-            boolean defaultOnly, ArrayList<ArrayList<F>> listCut) {
+            boolean defaultOnly, ArrayList<ArrayList<F>> listCut, int userId) {
         ArrayList<R> resultList = new ArrayList<R>();
 
         final boolean debug = localLOGV ||
@@ -212,13 +212,14 @@
         int N = listCut.size();
         for (int i = 0; i < N; ++i) {
             buildResolveList(intent, categories, debug, defaultOnly,
-                             resolvedType, scheme, listCut.get(i), resultList);
+                    resolvedType, scheme, listCut.get(i), resultList, userId);
         }
         sortResults(resultList);
         return resultList;
     }
 
-    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
+    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
+            int userId) {
         String scheme = intent.getScheme();
 
         ArrayList<R> finalList = new ArrayList<R>();
@@ -290,19 +291,19 @@
         FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
         if (firstTypeCut != null) {
             buildResolveList(intent, categories, debug, defaultOnly,
-                    resolvedType, scheme, firstTypeCut, finalList);
+                    resolvedType, scheme, firstTypeCut, finalList, userId);
         }
         if (secondTypeCut != null) {
             buildResolveList(intent, categories, debug, defaultOnly,
-                    resolvedType, scheme, secondTypeCut, finalList);
+                    resolvedType, scheme, secondTypeCut, finalList, userId);
         }
         if (thirdTypeCut != null) {
             buildResolveList(intent, categories, debug, defaultOnly,
-                    resolvedType, scheme, thirdTypeCut, finalList);
+                    resolvedType, scheme, thirdTypeCut, finalList, userId);
         }
         if (schemeCut != null) {
             buildResolveList(intent, categories, debug, defaultOnly,
-                    resolvedType, scheme, schemeCut, finalList);
+                    resolvedType, scheme, schemeCut, finalList, userId);
         }
         sortResults(finalList);
 
@@ -329,7 +330,7 @@
      * "stopped," that is whether it should not be included in the result
      * if the intent requests to excluded stopped objects.
      */
-    protected boolean isFilterStopped(F filter) {
+    protected boolean isFilterStopped(F filter, int userId) {
         return false;
     }
 
@@ -341,7 +342,7 @@
     protected abstract String packageForFilter(F filter);
     
     @SuppressWarnings("unchecked")
-    protected R newResult(F filter, int match) {
+    protected R newResult(F filter, int match, int userId) {
         return (R)filter;
     }
 
@@ -504,7 +505,7 @@
 
     private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
             boolean debug, boolean defaultOnly,
-            String resolvedType, String scheme, List<F> src, List<R> dest) {
+            String resolvedType, String scheme, List<F> src, List<R> dest, int userId) {
         final String action = intent.getAction();
         final Uri data = intent.getData();
         final String packageName = intent.getPackage();
@@ -519,7 +520,7 @@
             int match;
             if (debug) Slog.v(TAG, "Matching against filter " + filter);
 
-            if (excludingStopped && isFilterStopped(filter)) {
+            if (excludingStopped && isFilterStopped(filter, userId)) {
                 if (debug) {
                     Slog.v(TAG, "  Filter's target is stopped; skipping");
                 }
@@ -547,7 +548,7 @@
                 if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
                         Integer.toHexString(match));
                 if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
-                    final R oneResult = newResult(filter, match);
+                    final R oneResult = newResult(filter, match, userId);
                     if (oneResult != null) {
                         dest.add(oneResult);
                     }
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 366160b..510bdb2 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -48,6 +48,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserId;
 import android.os.storage.IMountService;
 import android.os.storage.IMountServiceListener;
 import android.os.storage.IMountShutdownObserver;
@@ -1674,7 +1675,7 @@
             return false;
         }
 
-        final int packageUid = mPms.getPackageUid(packageName);
+        final int packageUid = mPms.getPackageUid(packageName, UserId.getUserId(callerUid));
 
         if (DEBUG_OBB) {
             Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index 326b940..a7a46dd 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -30,8 +30,11 @@
 import android.media.AudioManager;
 import android.util.Log;
 
+import java.io.File;
 import java.io.FileReader;
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * <p>WiredAccessoryObserver monitors for a wired headset on the main board or dock.
@@ -39,17 +42,6 @@
 class WiredAccessoryObserver extends UEventObserver {
     private static final String TAG = WiredAccessoryObserver.class.getSimpleName();
     private static final boolean LOG = true;
-    private static final int MAX_AUDIO_PORTS = 3; /* h2w, USB Audio & hdmi */
-    private static final String uEventInfo[][] = { {"DEVPATH=/devices/virtual/switch/h2w",
-                                                    "/sys/class/switch/h2w/state",
-                                                    "/sys/class/switch/h2w/name"},
-                                                   {"DEVPATH=/devices/virtual/switch/usb_audio",
-                                                    "/sys/class/switch/usb_audio/state",
-                                                    "/sys/class/switch/usb_audio/name"},
-                                                   {"DEVPATH=/devices/virtual/switch/hdmi",
-                                                    "/sys/class/switch/hdmi/state",
-                                                    "/sys/class/switch/hdmi/name"} };
-
     private static final int BIT_HEADSET = (1 << 0);
     private static final int BIT_HEADSET_NO_MIC = (1 << 1);
     private static final int BIT_USB_HEADSET_ANLG = (1 << 2);
@@ -60,10 +52,89 @@
                                                    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;
+
+        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("DEVPATH=/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 static List<UEventInfo> makeObservedUEventList() {
+        List<UEventInfo> retVal = new ArrayList<UEventInfo>();
+        UEventInfo uei;
+
+        // Monitor h2w
+        uei = new UEventInfo("h2w", BIT_HEADSET, BIT_HEADSET_NO_MIC);
+        if (uei.checkSwitchExists()) {
+            retVal.add(uei);
+        } else {
+            Slog.w(TAG, "This kernel does not have wired headset support");
+        }
+
+        // Monitor USB
+        uei = new UEventInfo("usb_audio", BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL);
+        if (uei.checkSwitchExists()) {
+            retVal.add(uei);
+        } else {
+            Slog.w(TAG, "This kernel does not have usb audio support");
+        }
+
+        // Monitor HDMI
+        //
+        // If the kernel has support for the "hdmi_audio" switch, use that.  It will be signalled
+        // only when the HDMI driver has a video mode configured, and the downstream sink indicates
+        // support for audio in its EDID.
+        //
+        // If the kernel does not have an "hdmi_audio" switch, just fall back on the older "hdmi"
+        // switch instead.
+        uei = new UEventInfo("hdmi_audio", BIT_HDMI_AUDIO, 0);
+        if (uei.checkSwitchExists()) {
+            retVal.add(uei);
+        } else {
+            uei = new UEventInfo("hdmi", BIT_HDMI_AUDIO, 0);
+            if (uei.checkSwitchExists()) {
+                retVal.add(uei);
+            } else {
+                Slog.w(TAG, "This kernel does not have HDMI audio support");
+            }
+        }
+
+        return retVal;
+    }
+
+    private static List<UEventInfo> uEventInfo = makeObservedUEventList();
+
     private int mHeadsetState;
     private int mPrevHeadsetState;
     private String mHeadsetName;
-    private int switchState;
 
     private final Context mContext;
     private final WakeLock mWakeLock;  // held while there is a pending route change
@@ -85,11 +156,12 @@
         // one on the board, one on the dock and one on HDMI:
         // observe three UEVENTs
         init();  // set initial status
-        for (int i = 0; i < MAX_AUDIO_PORTS; i++) {
-            startObserving(uEventInfo[i][0]);
+        for (int i = 0; i < uEventInfo.size(); ++i) {
+            UEventInfo uei = uEventInfo.get(i);
+            startObserving(uei.getDevPath());
         }
       }
-  }
+    }
 
     @Override
     public void onUEvent(UEventObserver.UEvent event) {
@@ -106,50 +178,47 @@
 
     private synchronized final void updateState(String name, int state)
     {
-        if (name.equals("usb_audio")) {
-            switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|BIT_HDMI_AUDIO)) |
-                           ((state == 1) ? BIT_USB_HEADSET_ANLG :
-                                         ((state == 2) ? BIT_USB_HEADSET_DGTL : 0)));
-        } else if (name.equals("hdmi")) {
-            switchState = ((mHeadsetState & (BIT_HEADSET|BIT_HEADSET_NO_MIC|
-                                             BIT_USB_HEADSET_DGTL|BIT_USB_HEADSET_ANLG)) |
-                           ((state == 1) ? BIT_HDMI_AUDIO : 0));
-        } else {
-            switchState = ((mHeadsetState & (BIT_HDMI_AUDIO|BIT_USB_HEADSET_ANLG|
-                                             BIT_USB_HEADSET_DGTL)) |
-                            ((state == 1) ? BIT_HEADSET :
-                                          ((state == 2) ? BIT_HEADSET_NO_MIC : 0)));
+        // FIXME:  When ueventd informs of a change in state for a switch, it does not have to be
+        // the case that the name reported by /sys/class/switch/<device>/name is the same as
+        // <device>.  For normal users of the linux switch class driver, it will be.  But it is
+        // technically possible to hook the print_name method in the class driver and return a
+        // different name each and every time the name sysfs entry is queried.
+        //
+        // Right now this is not the case for any of the switch implementations used here.  I'm not
+        // certain anyone would ever choose to implement such a dynamic name, or what it would mean
+        // for the implementation at this level, but if it ever happens, we will need to revisit
+        // this code.
+        for (int i = 0; i < uEventInfo.size(); ++i) {
+            UEventInfo uei = uEventInfo.get(i);
+            if (name.equals(uei.getDevName())) {
+                update(name, uei.computeNewHeadsetState(mHeadsetState, state));
+                return;
+            }
         }
-        update(name, switchState);
     }
 
     private synchronized final void init() {
         char[] buffer = new char[1024];
-
-        String newName = mHeadsetName;
-        int newState = mHeadsetState;
         mPrevHeadsetState = mHeadsetState;
 
         if (LOG) Slog.v(TAG, "init()");
 
-        for (int i = 0; i < MAX_AUDIO_PORTS; i++) {
+        for (int i = 0; i < uEventInfo.size(); ++i) {
+            UEventInfo uei = uEventInfo.get(i);
             try {
-                FileReader file = new FileReader(uEventInfo[i][1]);
+                int curState;
+                FileReader file = new FileReader(uei.getSwitchStatePath());
                 int len = file.read(buffer, 0, 1024);
                 file.close();
-                newState = Integer.valueOf((new String(buffer, 0, len)).trim());
+                curState = Integer.valueOf((new String(buffer, 0, len)).trim());
 
-                file = new FileReader(uEventInfo[i][2]);
-                len = file.read(buffer, 0, 1024);
-                file.close();
-                newName = new String(buffer, 0, len).trim();
-
-                if (newState > 0) {
-                    updateState(newName, newState);
+                if (curState > 0) {
+                    updateState(uei.getDevName(), curState);
                 }
 
             } catch (FileNotFoundException e) {
-                Slog.w(TAG, "This kernel does not have wired headset support");
+                Slog.w(TAG, uei.getSwitchStatePath() +
+                        " not found while attempting to determine initial switch state");
             } catch (Exception e) {
                 Slog.e(TAG, "" , e);
             }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index dd1dac2..60749b3 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -34,6 +34,7 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.AlertDialog;
 import android.app.AppGlobals;
@@ -1079,7 +1080,8 @@
                     int uid = msg.arg1;
                     boolean restart = (msg.arg2 == 1);
                     String pkg = (String) msg.obj;
-                    forceStopPackageLocked(pkg, uid, restart, false, true, false);
+                    forceStopPackageLocked(pkg, uid, restart, false, true, false,
+                            UserId.getUserId(uid));
                 }
             } break;
             case FINALIZE_PENDING_INTENT_MSG: {
@@ -1289,7 +1291,7 @@
 
             ApplicationInfo info =
                 mSelf.mContext.getPackageManager().getApplicationInfo(
-                        "android", STOCK_PM_FLAGS);
+                            "android", STOCK_PM_FLAGS);
             mSystemThread.installSystemApplicationInfo(info);
        
             synchronized (mSelf) {
@@ -2352,10 +2354,12 @@
         synchronized (this) {
             ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
             if (r == null) {
+                ActivityOptions.abort(options);
                 return false;
             }
             if (r.app == null || r.app.thread == null) {
                 // The caller is not running...  d'oh!
+                ActivityOptions.abort(options);
                 return false;
             }
             intent = new Intent(intent);
@@ -2369,7 +2373,8 @@
                 List<ResolveInfo> resolves =
                     AppGlobals.getPackageManager().queryIntentActivities(
                             intent, r.resolvedType,
-                            PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
+                            PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
+                            UserId.getCallingUserId());
 
                 // Look for the original activity in the list...
                 final int N = resolves != null ? resolves.size() : 0;
@@ -2391,6 +2396,7 @@
 
             if (aInfo == null) {
                 // Nobody who is next!
+                ActivityOptions.abort(options);
                 return false;
             }
 
@@ -2420,8 +2426,6 @@
             }
 
             final long origId = Binder.clearCallingIdentity();
-            // XXX we are not dealing with propagating grantedUriPermissions...
-            // those are not yet exposed to user code, so there is no need.
             int res = mMainStack.startActivityLocked(r.app.thread, intent,
                     r.resolvedType, aInfo, resultTo != null ? resultTo.appToken : null,
                     resultWho, requestCode, -1, r.launchedFromUid, 0,
@@ -3291,7 +3295,7 @@
             int pkgUid = -1;
             synchronized(this) {
                 try {
-                    pkgUid = pm.getPackageUid(packageName);
+                    pkgUid = pm.getPackageUid(packageName, userId);
                 } catch (RemoteException e) {
                 }
                 if (pkgUid == -1) {
@@ -3312,7 +3316,7 @@
             
             try {
                 //clear application user data
-                pm.clearApplicationUserData(packageName, observer);
+                pm.clearApplicationUserData(packageName, observer, userId);
                 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
                         Uri.fromParts("package", packageName, null));
                 intent.putExtra(Intent.EXTRA_UID, pkgUid);
@@ -3339,13 +3343,14 @@
             throw new SecurityException(msg);
         }
         
+        int userId = UserId.getCallingUserId();
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
             int pkgUid = -1;
             synchronized(this) {
                 try {
-                    pkgUid = pm.getPackageUid(packageName);
+                    pkgUid = pm.getPackageUid(packageName, userId);
                 } catch (RemoteException e) {
                 }
                 if (pkgUid == -1) {
@@ -3412,16 +3417,14 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        final int userId = Binder.getOrigCallingUser();
+        final int userId = UserId.getCallingUserId();
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
             int pkgUid = -1;
             synchronized(this) {
                 try {
-                    pkgUid = pm.getPackageUid(packageName);
-                    // Convert the uid to the one for the calling user
-                    pkgUid = UserId.getUid(userId, pkgUid);
+                    pkgUid = pm.getPackageUid(packageName, userId);
                 } catch (RemoteException e) {
                 }
                 if (pkgUid == -1) {
@@ -3430,7 +3433,7 @@
                 }
                 forceStopPackageLocked(packageName, pkgUid);
                 try {
-                    pm.setPackageStoppedState(packageName, true);
+                    pm.setPackageStoppedState(packageName, true, userId);
                 } catch (RemoteException e) {
                 } catch (IllegalArgumentException e) {
                     Slog.w(TAG, "Failed trying to unstop package "
@@ -3545,7 +3548,7 @@
     }
 
     private void forceStopPackageLocked(final String packageName, int uid) {
-        forceStopPackageLocked(packageName, uid, false, false, true, false);
+        forceStopPackageLocked(packageName, uid, false, false, true, false, UserId.getUserId(uid));
         Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
                 Uri.fromParts("package", packageName, null));
         if (!mProcessesReady) {
@@ -3602,13 +3605,13 @@
 
     private final boolean forceStopPackageLocked(String name, int uid,
             boolean callerWillRestart, boolean purgeCache, boolean doit,
-            boolean evenPersistent) {
+            boolean evenPersistent, int userId) {
         int i;
         int N;
 
         if (uid < 0) {
             try {
-                uid = AppGlobals.getPackageManager().getPackageUid(name);
+                uid = AppGlobals.getPackageManager().getPackageUid(name, userId);
             } catch (RemoteException e) {
             }
         }
@@ -3652,14 +3655,13 @@
                 }
                 lastTask = r.task;
                 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
-                        null, "force-stop")) {
+                        null, "force-stop", true)) {
                     i--;
                 }
             }
         }
 
         ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
-        int userId = UserId.getUserId(uid);
         for (ServiceRecord service : mServiceMap.getAllServices(userId)) {
             if (service.packageName.equals(name)
                     && (service.app == null || evenPersistent || !service.app.persistent)) {
@@ -4107,11 +4109,11 @@
                 if (pkgs != null) {
                     for (String pkg : pkgs) {
                         synchronized (ActivityManagerService.this) {
-                          if (forceStopPackageLocked(pkg, -1, false, false, false, false)) {
-                              setResultCode(Activity.RESULT_OK);
-                              return;
-                          }
-                       }
+                            if (forceStopPackageLocked(pkg, -1, false, false, false, false, 0)) {
+                                setResultCode(Activity.RESULT_OK);
+                                return;
+                            }
+                        }
                     }
                 }
             }
@@ -4290,8 +4292,8 @@
             try {
                 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
                     int uid = AppGlobals.getPackageManager()
-                            .getPackageUid(packageName);
-                    if (UserId.getAppId(callingUid) != uid) {
+                            .getPackageUid(packageName, UserId.getUserId(callingUid));
+                    if (!UserId.isSameApp(callingUid, uid)) {
                         String msg = "Permission Denial: getIntentSender() from pid="
                             + Binder.getCallingPid()
                             + ", uid=" + Binder.getCallingUid()
@@ -4386,7 +4388,7 @@
             PendingIntentRecord rec = (PendingIntentRecord)sender;
             try {
                 int uid = AppGlobals.getPackageManager()
-                        .getPackageUid(rec.key.packageName);
+                        .getPackageUid(rec.key.packageName, UserId.getCallingUserId());
                 if (!UserId.isSameApp(uid, Binder.getCallingUid())) {
                     String msg = "Permission Denial: cancelIntentSender() from pid="
                         + Binder.getCallingPid()
@@ -4796,7 +4798,7 @@
         } else {
             try {
                 pi = pm.resolveContentProvider(name,
-                        PackageManager.GET_URI_PERMISSION_PATTERNS);
+                        PackageManager.GET_URI_PERMISSION_PATTERNS, UserId.getUserId(callingUid));
             } catch (RemoteException ex) {
             }
         }
@@ -4808,7 +4810,7 @@
         int targetUid = lastTargetUid;
         if (targetUid < 0 && targetPkg != null) {
             try {
-                targetUid = pm.getPackageUid(targetPkg);
+                targetUid = pm.getPackageUid(targetPkg, UserId.getUserId(callingUid));
                 if (targetUid < 0) {
                     if (DEBUG_URI_PERMISSION) Slog.v(TAG,
                             "Can't grant URI permission no uid for: " + targetPkg);
@@ -5100,14 +5102,14 @@
 
         final String authority = uri.getAuthority();
         ProviderInfo pi = null;
-        ContentProviderRecord cpr = mProviderMap.getProviderByName(authority,
-                UserId.getUserId(callingUid));
+        int userId = UserId.getUserId(callingUid);
+        ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId);
         if (cpr != null) {
             pi = cpr.info;
         } else {
             try {
                 pi = pm.resolveContentProvider(authority,
-                        PackageManager.GET_URI_PERMISSION_PATTERNS);
+                        PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
             } catch (RemoteException ex) {
             }
         }
@@ -5202,7 +5204,7 @@
             } else {
                 try {
                     pi = pm.resolveContentProvider(authority,
-                            PackageManager.GET_URI_PERMISSION_PATTERNS);
+                            PackageManager.GET_URI_PERMISSION_PATTERNS, r.userId);
                 } catch (RemoteException ex) {
                 }
             }
@@ -5480,12 +5482,13 @@
                         // Check whether this activity is currently available.
                         try {
                             if (rti.origActivity != null) {
-                                if (pm.getActivityInfo(rti.origActivity, 0) == null) {
+                                if (pm.getActivityInfo(rti.origActivity, 0, callingUserId)
+                                        == null) {
                                     continue;
                                 }
                             } else if (rti.baseIntent != null) {
                                 if (pm.queryIntentActivities(rti.baseIntent,
-                                        null, 0) == null) {
+                                        null, 0, callingUserId) == null) {
                                     continue;
                                 }
                             }
@@ -5685,13 +5688,14 @@
     /**
      * TODO: Add mController hook
      */
-    public void moveTaskToFront(int task, int flags) {
+    public void moveTaskToFront(int task, int flags, Bundle options) {
         enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
                 "moveTaskToFront()");
 
         synchronized(this) {
             if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
                     Binder.getCallingUid(), "Task to front")) {
+                ActivityOptions.abort(options);
                 return;
             }
             final long origId = Binder.clearCallingIdentity();
@@ -5706,7 +5710,7 @@
                         // we'll just move the home task to the top first.
                         mMainStack.moveHomeToFrontLocked();
                     }
-                    mMainStack.moveTaskToFrontLocked(tr, null);
+                    mMainStack.moveTaskToFrontLocked(tr, null, options);
                     return;
                 }
                 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
@@ -5720,13 +5724,14 @@
                             // we'll just move the home task to the top first.
                             mMainStack.moveHomeToFrontLocked();
                         }
-                        mMainStack.moveTaskToFrontLocked(hr.task, null);
+                        mMainStack.moveTaskToFrontLocked(hr.task, null, options);
                         return;
                     }
                 }
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
+            ActivityOptions.abort(options);
         }
     }
 
@@ -6132,15 +6137,14 @@
                 try {
                     cpi = AppGlobals.getPackageManager().
                         resolveContentProvider(name,
-                                STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
+                            STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
                 } catch (RemoteException ex) {
                 }
                 if (cpi == null) {
                     return null;
                 }
 
-                cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo,
-                        Binder.getOrigCallingUser());
+                cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
 
                 String msg;
                 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
@@ -6157,7 +6161,7 @@
                 }
 
                 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
-                cpr = mProviderMap.getProviderByClass(comp, Binder.getOrigCallingUser());
+                cpr = mProviderMap.getProviderByClass(comp, userId);
                 final boolean firstClass = cpr == null;
                 if (firstClass) {
                     try {
@@ -6165,13 +6169,13 @@
                             AppGlobals.getPackageManager().
                                 getApplicationInfo(
                                         cpi.applicationInfo.packageName,
-                                        STOCK_PM_FLAGS);
+                                        STOCK_PM_FLAGS, userId);
                         if (ai == null) {
                             Slog.w(TAG, "No package info for content provider "
                                     + cpi.name);
                             return null;
                         }
-                        ai = getAppInfoForUser(ai, Binder.getOrigCallingUser());
+                        ai = getAppInfoForUser(ai, userId);
                         cpr = new ContentProviderRecord(this, cpi, ai, comp);
                     } catch (RemoteException ex) {
                         // pm is in same process, this will never happen.
@@ -6212,7 +6216,7 @@
                         // Content provider is now in use, its package can't be stopped.
                         try {
                             AppGlobals.getPackageManager().setPackageStoppedState(
-                                    cpr.appInfo.packageName, false);
+                                    cpr.appInfo.packageName, false, userId);
                         } catch (RemoteException e) {
                         } catch (IllegalArgumentException e) {
                             Slog.w(TAG, "Failed trying to unstop package "
@@ -6546,7 +6550,7 @@
         // This package really, really can not be stopped.
         try {
             AppGlobals.getPackageManager().setPackageStoppedState(
-                    info.packageName, false);
+                    info.packageName, false, UserId.getUserId(app.uid));
         } catch (RemoteException e) {
         } catch (IllegalArgumentException e) {
             Slog.w(TAG, "Failed trying to unstop package "
@@ -6778,7 +6782,7 @@
             mDebugTransient = !persistent;
             if (packageName != null) {
                 final long origId = Binder.clearCallingIdentity();
-                forceStopPackageLocked(packageName, -1, false, false, true, true);
+                forceStopPackageLocked(packageName, -1, false, false, true, true, 0);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -7173,7 +7177,7 @@
                 List<ResolveInfo> ris = null;
                 try {
                     ris = AppGlobals.getPackageManager().queryIntentReceivers(
-                                intent, null, 0);
+                            intent, null, 0, 0);
                 } catch (RemoteException e) {
                 }
                 if (ris != null) {
@@ -7430,6 +7434,10 @@
     }
 
     private boolean handleAppCrashLocked(ProcessRecord app) {
+        if (mHeadless) {
+            Log.e(TAG, "handleAppCrashLocked: " + app.processName);
+            return false;
+        }
         long now = SystemClock.uptimeMillis();
 
         Long crashTime;
@@ -7477,7 +7485,7 @@
             mMainStack.resumeTopActivityLocked(null);
         } else {
             ActivityRecord r = mMainStack.topRunningActivityLocked(null);
-            if (r.app == app) {
+            if (r != null && r.app == app) {
                 // If the top running activity is from this crashing
                 // process, then terminate it to avoid getting in a loop.
                 Slog.w(TAG, "  Force finishing activity "
@@ -7839,7 +7847,7 @@
             for (String pkg : process.pkgList) {
                 sb.append("Package: ").append(pkg);
                 try {
-                    PackageInfo pi = pm.getPackageInfo(pkg, 0);
+                    PackageInfo pi = pm.getPackageInfo(pkg, 0, 0);
                     if (pi != null) {
                         sb.append(" v").append(pi.versionCode);
                         if (pi.versionName != null) {
@@ -8237,7 +8245,7 @@
             IPackageManager pm = AppGlobals.getPackageManager();
             for (String pkg : extList) {
                 try {
-                    ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
+                    ApplicationInfo info = pm.getApplicationInfo(pkg, 0, UserId.getCallingUserId());
                     if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                         retList.add(info);
                     }
@@ -10718,21 +10726,21 @@
     };
 
     private ServiceLookupResult findServiceLocked(Intent service,
-            String resolvedType) {
+            String resolvedType, int userId) {
         ServiceRecord r = null;
         if (service.getComponent() != null) {
-            r = mServiceMap.getServiceByName(service.getComponent(), Binder.getOrigCallingUser());
+            r = mServiceMap.getServiceByName(service.getComponent(), userId);
         }
         if (r == null) {
             Intent.FilterComparison filter = new Intent.FilterComparison(service);
-            r = mServiceMap.getServiceByIntent(filter, Binder.getOrigCallingUser());
+            r = mServiceMap.getServiceByIntent(filter, userId);
         }
 
         if (r == null) {
             try {
                 ResolveInfo rInfo =
                     AppGlobals.getPackageManager().resolveService(
-                            service, resolvedType, 0);
+                                service, resolvedType, 0, userId);
                 ServiceInfo sInfo =
                     rInfo != null ? rInfo.serviceInfo : null;
                 if (sInfo == null) {
@@ -10803,7 +10811,7 @@
             try {
                 ResolveInfo rInfo =
                     AppGlobals.getPackageManager().resolveService(
-                            service, resolvedType, STOCK_PM_FLAGS);
+                                service, resolvedType, STOCK_PM_FLAGS, userId);
                 ServiceInfo sInfo =
                     rInfo != null ? rInfo.serviceInfo : null;
                 if (sInfo == null) {
@@ -11168,7 +11176,7 @@
         // Service is now being launched, its package can't be stopped.
         try {
             AppGlobals.getPackageManager().setPackageStoppedState(
-                    r.packageName, false);
+                    r.packageName, false, r.userId);
         } catch (RemoteException e) {
         } catch (IllegalArgumentException e) {
             Slog.w(TAG, "Failed trying to unstop package "
@@ -11473,7 +11481,8 @@
             }
 
             // If this service is active, make sure it is stopped.
-            ServiceLookupResult r = findServiceLocked(service, resolvedType);
+            ServiceLookupResult r = findServiceLocked(service, resolvedType,
+                    callerApp == null ? UserId.getCallingUserId() : callerApp.userId);
             if (r != null) {
                 if (r.record != null) {
                     final long origId = Binder.clearCallingIdentity();
@@ -11501,7 +11510,8 @@
         IBinder ret = null;
 
         synchronized(this) {
-            ServiceLookupResult r = findServiceLocked(service, resolvedType);
+            ServiceLookupResult r = findServiceLocked(service, resolvedType,
+                    UserId.getCallingUserId());
             
             if (r != null) {
                 // r.record is null if findServiceLocked() failed the caller permission check
@@ -12130,7 +12140,7 @@
             // Backup agent is now in use, its package can't be stopped.
             try {
                 AppGlobals.getPackageManager().setPackageStoppedState(
-                        app.packageName, false);
+                        app.packageName, false, UserId.getUserId(app.uid));
             } catch (RemoteException e) {
             } catch (IllegalArgumentException e) {
                 Slog.w(TAG, "Failed trying to unstop package "
@@ -12494,7 +12504,7 @@
                         String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                         if (list != null && (list.length > 0)) {
                             for (String pkg : list) {
-                                forceStopPackageLocked(pkg, -1, false, true, true, false);
+                                forceStopPackageLocked(pkg, -1, false, true, true, false, userId);
                             }
                             sendPackageBroadcastLocked(
                                     IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
@@ -12505,7 +12515,8 @@
                         if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
                             if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
                                 forceStopPackageLocked(ssp,
-                                        intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false);
+                                        intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true,
+                                        false, userId);
                             }
                             if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                                 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
@@ -12622,7 +12633,7 @@
             if (intent.getComponent() != null) {
                 // Broadcast is going to one specific receiver class...
                 ActivityInfo ai = AppGlobals.getPackageManager().
-                    getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
+                        getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS, userId);
                 if (ai != null) {
                     receivers = new ArrayList();
                     ResolveInfo ri = new ResolveInfo();
@@ -12630,15 +12641,15 @@
                     receivers.add(ri);
                 }
             } else {
-                // TODO: Apply userId
                 // Need to resolve the intent to interested receivers...
                 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                          == 0) {
                     receivers =
                         AppGlobals.getPackageManager().queryIntentReceivers(
-                                intent, resolvedType, STOCK_PM_FLAGS);
+                                    intent, resolvedType, STOCK_PM_FLAGS, userId);
                 }
-                registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
+                registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false,
+                        userId);
             }
         } catch (RemoteException ex) {
             // pm is in same process, this will never happen.
@@ -12929,7 +12940,7 @@
                 ii = mContext.getPackageManager().getInstrumentationInfo(
                     className, STOCK_PM_FLAGS);
                 ai = mContext.getPackageManager().getApplicationInfo(
-                    ii.targetPackage, STOCK_PM_FLAGS);
+                        ii.targetPackage, STOCK_PM_FLAGS);
             } catch (PackageManager.NameNotFoundException e) {
             }
             if (ii == null) {
@@ -12957,9 +12968,10 @@
                 throw new SecurityException(msg);
             }
 
+            int userId = UserId.getCallingUserId();
             final long origId = Binder.clearCallingIdentity();
             // Instrumentation can kill and relaunch even persistent processes
-            forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true);
+            forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId);
             ProcessRecord app = addAppLocked(ai, false);
             app.instrumentationClass = className;
             app.instrumentationInfo = ai;
@@ -13014,11 +13026,12 @@
         app.instrumentationProfileFile = null;
         app.instrumentationArguments = null;
 
-        forceStopPackageLocked(app.processName, -1, false, false, true, true);
+        forceStopPackageLocked(app.processName, -1, false, false, true, true, app.userId);
     }
 
     public void finishInstrumentation(IApplicationThread target,
             int resultCode, Bundle results) {
+        int userId = UserId.getCallingUserId();
         // Refuse possible leaked file descriptors
         if (results != null && results.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 53cb2b0..d60ff2b 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -26,7 +26,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.res.CompatibilityInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.os.Build;
@@ -542,24 +541,38 @@
 
     void updateOptionsLocked(Bundle options) {
         if (options != null) {
+            if (pendingOptions != null) {
+                pendingOptions.abort();
+            }
             pendingOptions = new ActivityOptions(options);
         }
     }
 
     void applyOptionsLocked() {
         if (pendingOptions != null) {
-            if (pendingOptions.isCustomAnimation()) {
-                service.mWindowManager.overridePendingAppTransition(
-                        pendingOptions.getPackageName(),
-                        pendingOptions.getCustomEnterResId(),
-                        pendingOptions.getCustomExitResId());
+            switch (pendingOptions.getAnimationType()) {
+                case ActivityOptions.ANIM_CUSTOM:
+                    service.mWindowManager.overridePendingAppTransition(
+                            pendingOptions.getPackageName(),
+                            pendingOptions.getCustomEnterResId(),
+                            pendingOptions.getCustomExitResId());
+                    break;
+                case ActivityOptions.ANIM_THUMBNAIL:
+                    service.mWindowManager.overridePendingAppTransitionThumb(
+                            pendingOptions.getThumbnail(),
+                            pendingOptions.getStartX(), pendingOptions.getStartY(),
+                            pendingOptions.getOnAnimationStartListener());
+                    break;
             }
             pendingOptions = null;
         }
     }
 
     void clearOptionsLocked() {
-        pendingOptions = null;
+        if (pendingOptions != null) {
+            pendingOptions.abort();
+            pendingOptions = null;
+        }
     }
 
     void removeUriPermissionsLocked() {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 7e8df35..a01ed25 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1445,9 +1445,8 @@
         // Launching this app's activity, make sure the app is no longer
         // considered stopped.
         try {
-            // TODO: Apply to the correct userId
             AppGlobals.getPackageManager().setPackageStoppedState(
-                    next.packageName, false);
+                    next.packageName, false, next.userId); /* TODO: Verify if correct userid */
         } catch (RemoteException e1) {
         } catch (IllegalArgumentException e) {
             Slog.w(TAG, "Failed trying to unstop package "
@@ -1696,6 +1695,7 @@
                         if (VALIDATE_TOKENS) {
                             validateAppTokensLocked();
                         }
+                        ActivityOptions.abort(options);
                         return;
                     }
                     break;
@@ -1798,6 +1798,7 @@
             // because there is nothing for it to animate on top of.
             mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
                     r.info.screenOrientation, r.fullscreen);
+            ActivityOptions.abort(options);
         }
         if (VALIDATE_TOKENS) {
             validateAppTokensLocked();
@@ -2345,6 +2346,7 @@
             // Transfer the result target from the source activity to the new
             // one being started, including any failures.
             if (requestCode >= 0) {
+                ActivityOptions.abort(options);
                 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
             }
             resultRecord = sourceRecord.resultTo;
@@ -2376,6 +2378,7 @@
                     Activity.RESULT_CANCELED, null);
             }
             mDismissKeyguardOnNextActivity = false;
+            ActivityOptions.abort(options);
             return err;
         }
 
@@ -2426,6 +2429,7 @@
                     // We pretend to the caller that it was really started, but
                     // they will just get a cancel result.
                     mDismissKeyguardOnNextActivity = false;
+                    ActivityOptions.abort(options);
                     return ActivityManager.START_SUCCESS;
                 }
             }
@@ -2448,6 +2452,7 @@
                     pal.startFlags = startFlags;
                     mService.mPendingActivityLaunches.add(pal);
                     mDismissKeyguardOnNextActivity = false;
+                    ActivityOptions.abort(options);
                     return ActivityManager.START_SWITCHES_CANCELED;
                 }
             }
@@ -2602,8 +2607,7 @@
                             // We really do want to push this one into the
                             // user's face, right now.
                             moveHomeToFrontFromLaunchLocked(launchFlags);
-                            r.updateOptionsLocked(options);
-                            moveTaskToFrontLocked(taskTop.task, r);
+                            moveTaskToFrontLocked(taskTop.task, r, options);
                         }
                     }
                     // If the caller has requested that the target task be
@@ -2619,6 +2623,7 @@
                         if (doResume) {
                             resumeTopActivityLocked(null);
                         }
+                        ActivityOptions.abort(options);
                         return ActivityManager.START_RETURN_INTENT_TO_CALLER;
                     }
                     if ((launchFlags &
@@ -2706,6 +2711,7 @@
                         if (doResume) {
                             resumeTopActivityLocked(null);
                         }
+                        ActivityOptions.abort(options);
                         return ActivityManager.START_TASK_TO_FRONT;
                     }
                 }
@@ -2735,6 +2741,7 @@
                             if (doResume) {
                                 resumeTopActivityLocked(null);
                             }
+                            ActivityOptions.abort(options);
                             if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
                                 // We don't need to start a new activity, and
                                 // the client said not to do anything if that
@@ -2754,6 +2761,7 @@
                         r.resultTo, r.resultWho, r.requestCode,
                     Activity.RESULT_CANCELED, null);
             }
+            ActivityOptions.abort(options);
             return ActivityManager.START_CLASS_NOT_FOUND;
         }
 
@@ -2795,6 +2803,7 @@
                     if (doResume) {
                         resumeTopActivityLocked(null);
                     }
+                    ActivityOptions.abort(options);
                     return ActivityManager.START_DELIVERED_TO_TOP;
                 }
             } else if (!addingToTask &&
@@ -2847,7 +2856,7 @@
     }
 
     ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
-             String profileFile, ParcelFileDescriptor profileFd) {
+            String profileFile, ParcelFileDescriptor profileFd, int userId) {
         // Collect information about the target of the Intent.
         ActivityInfo aInfo;
         try {
@@ -2855,7 +2864,7 @@
                 AppGlobals.getPackageManager().resolveIntent(
                         intent, resolvedType,
                         PackageManager.MATCH_DEFAULT_ONLY
-                        | ActivityManagerService.STOCK_PM_FLAGS);
+                                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
             aInfo = rInfo != null ? rInfo.activityInfo : null;
         } catch (RemoteException e) {
             aInfo = null;
@@ -2909,7 +2918,7 @@
 
         // Collect information about the target of the Intent.
         ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
-                profileFile, profileFd);
+                profileFile, profileFd, userId);
         aInfo = mService.getActivityInfoForUser(aInfo, userId);
 
         synchronized (mService) {
@@ -2949,6 +2958,7 @@
                                 Slog.w(TAG, "Unable to find app for caller " + caller
                                       + " (pid=" + realCallingPid + ") when starting: "
                                       + intent.toString());
+                                ActivityOptions.abort(options);
                                 return ActivityManager.START_PERMISSION_DENIED;
                             }
                         }
@@ -2989,7 +2999,7 @@
                                 AppGlobals.getPackageManager().resolveIntent(
                                         intent, null,
                                         PackageManager.MATCH_DEFAULT_ONLY
-                                        | ActivityManagerService.STOCK_PM_FLAGS);
+                                        | ActivityManagerService.STOCK_PM_FLAGS, userId);
                             aInfo = rInfo != null ? rInfo.activityInfo : null;
                             aInfo = mService.getActivityInfoForUser(aInfo, userId);
                         } catch (RemoteException e) {
@@ -3098,7 +3108,7 @@
 
                     // Collect information about the target of the Intent.
                     ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
-                            0, null, null);
+                            0, null, null, userId);
                     // TODO: New, check if this is correct
                     aInfo = mService.getActivityInfoForUser(aInfo, userId);
 
@@ -3481,6 +3491,15 @@
      */
     final boolean finishActivityLocked(ActivityRecord r, int index,
             int resultCode, Intent resultData, String reason) {
+        return finishActivityLocked(r, index, resultCode, resultData, reason, false);
+    }
+
+    /**
+     * @return Returns true if this activity has been removed from the history
+     * list, or false if it is still in the list and will be removed later.
+     */
+    final boolean finishActivityLocked(ActivityRecord r, int index,
+            int resultCode, Intent resultData, String reason, boolean immediate) {
         if (r.finishing) {
             Slog.w(TAG, "Duplicate finish request for " + r);
             return false;
@@ -3522,7 +3541,10 @@
             mService.mCancelledThumbnails.add(r);
         }
 
-        if (mResumedActivity == r) {
+        if (immediate) {
+            return finishCurrentActivityLocked(r, index,
+                    FINISH_IMMEDIATELY) == null;
+        } else if (mResumedActivity == r) {
             boolean endTask = index <= 0
                     || (mHistory.get(index-1)).task != r.task;
             if (DEBUG_TRANSITION) Slog.v(TAG,
@@ -3888,12 +3910,12 @@
             }
         }
         if (homeTask != null) {
-            moveTaskToFrontLocked(homeTask, null);
+            moveTaskToFrontLocked(homeTask, null, null);
         }
     }
 
 
-    final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason) {
+    final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
         if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
 
         final int task = tr.taskId;
@@ -3901,6 +3923,7 @@
 
         if (top < 0 || (mHistory.get(top)).task.taskId == task) {
             // nothing to do!
+            ActivityOptions.abort(options);
             return;
         }
 
@@ -3942,7 +3965,16 @@
             if (r != null) {
                 mNoAnimActivities.add(r);
             }
+            ActivityOptions.abort(options);
         } else {
+            if (options != null) {
+                ActivityRecord r = topRunningActivityLocked(null);
+                if (r != null && r.state != ActivityState.RESUMED) {
+                    r.updateOptionsLocked(options);
+                } else {
+                    ActivityOptions.abort(options);
+                }
+            }
             mService.mWindowManager.prepareAppTransition(
                     WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, false);
         }
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 39b63db..1b83e0b 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -732,7 +732,7 @@
             // Broadcast is being executed, its package can't be stopped.
             try {
                 AppGlobals.getPackageManager().setPackageStoppedState(
-                        r.curComponent.getPackageName(), false);
+                        r.curComponent.getPackageName(), false, UserId.getUserId(r.callingUid));
             } catch (RemoteException e) {
             } catch (IllegalArgumentException e) {
                 Slog.w(TAG, "Failed trying to unstop package "
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index cd72202..3ba3fbb 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -121,7 +121,7 @@
     public void handlePackageAddedLocked(String packageName, boolean updated) {
         ApplicationInfo ai = null;
         try {
-            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
         } catch (RemoteException e) {
         }
         if (ai == null) {
@@ -220,7 +220,7 @@
     public int getPackageScreenCompatModeLocked(String packageName) {
         ApplicationInfo ai = null;
         try {
-            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
         } catch (RemoteException e) {
         }
         if (ai == null) {
@@ -232,7 +232,7 @@
     public void setPackageScreenCompatModeLocked(String packageName, int mode) {
         ApplicationInfo ai = null;
         try {
-            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0, 0);
         } catch (RemoteException e) {
         }
         if (ai == null) {
@@ -365,7 +365,7 @@
                 }
                 ApplicationInfo ai = null;
                 try {
-                    ai = pm.getApplicationInfo(pkg, 0);
+                    ai = pm.getApplicationInfo(pkg, 0, 0);
                 } catch (RemoteException e) {
                 }
                 if (ai == null) {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index bb0f987..067bf28 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -395,7 +395,7 @@
     static final int MCS_GIVE_UP = 11;
     static final int UPDATED_MEDIA_STATUS = 12;
     static final int WRITE_SETTINGS = 13;
-    static final int WRITE_STOPPED_PACKAGES = 14;
+    static final int WRITE_PACKAGE_RESTRICTIONS = 14;
     static final int PACKAGE_VERIFIED = 15;
     static final int CHECK_PENDING_VERIFICATION = 16;
 
@@ -406,6 +406,9 @@
 
     final UserManager mUserManager;
 
+    // Stores a list of users whose package restrictions file needs to be updated
+    private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
+
     final private DefaultContainerConnection mDefContainerConn =
             new DefaultContainerConnection();
     class DefaultContainerConnection implements ServiceConnection {
@@ -629,7 +632,7 @@
                             packages[i] = ent.getKey();
                             components[i] = ent.getValue();
                             PackageSetting ps = mSettings.mPackages.get(ent.getKey());
-                            uids[i] = (ps != null) ? ps.userId : -1;
+                            uids[i] = (ps != null) ? ps.uid : -1;
                             i++;
                         }
                         size = i;
@@ -735,16 +738,20 @@
                     Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                     synchronized (mPackages) {
                         removeMessages(WRITE_SETTINGS);
-                        removeMessages(WRITE_STOPPED_PACKAGES);
+                        removeMessages(WRITE_PACKAGE_RESTRICTIONS);
                         mSettings.writeLPr();
+                        mDirtyUsers.clear();
                     }
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                 } break;
-                case WRITE_STOPPED_PACKAGES: {
+                case WRITE_PACKAGE_RESTRICTIONS: {
                     Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                     synchronized (mPackages) {
-                        removeMessages(WRITE_STOPPED_PACKAGES);
-                        mSettings.writeStoppedLPr();
+                        removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+                        for (int userId : mDirtyUsers) {
+                            mSettings.writePackageRestrictionsLPr(userId);
+                        }
+                        mDirtyUsers.clear();
                     }
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                 } break;
@@ -811,10 +818,11 @@
             mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
         }
     }
-    
-    void scheduleWriteStoppedPackagesLocked() {
-        if (!mHandler.hasMessages(WRITE_STOPPED_PACKAGES)) {
-            mHandler.sendEmptyMessageDelayed(WRITE_STOPPED_PACKAGES, WRITE_SETTINGS_DELAY);
+
+    void scheduleWritePackageRestrictionsLocked(int userId) {
+        mDirtyUsers.add(userId);
+        if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
+            mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
         }
     }
 
@@ -916,7 +924,7 @@
 
             readPermissions();
 
-            mRestoredSettings = mSettings.readLPw();
+            mRestoredSettings = mSettings.readLPw(getUsers());
             long startTime = SystemClock.uptimeMillis();
 
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
@@ -1180,7 +1188,7 @@
     private String getRequiredVerifierLPr() {
         final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
         final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
-                PackageManager.GET_DISABLED_COMPONENTS);
+                PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
 
         String requiredVerifier = null;
 
@@ -1512,7 +1520,8 @@
                 ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions);
     }
 
-    public PackageInfo getPackageInfo(String packageName, int flags) {
+    @Override
+    public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
         // reader
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
@@ -1522,7 +1531,7 @@
                 return generatePackageInfo(p, flags);
             }
             if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
-                return generatePackageInfoFromSettingsLPw(packageName, flags);
+                return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
             }
         }
         return null;
@@ -1551,20 +1560,21 @@
         }
         return out;
     }
-    
-    public int getPackageUid(String packageName) {
+
+    @Override
+    public int getPackageUid(String packageName, int userId) {
         // reader
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
             if(p != null) {
-                return p.applicationInfo.uid;
+                return UserId.getUid(userId, p.applicationInfo.uid);
             }
             PackageSetting ps = mSettings.mPackages.get(packageName);
             if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
                 return -1;
             }
             p = ps.pkg;
-            return p != null ? p.applicationInfo.uid : -1;
+            return p != null ? UserId.getUid(userId, p.applicationInfo.uid) : -1;
         }
     }
 
@@ -1661,11 +1671,12 @@
         }
     }
 
-    private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags) {
+    private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
+            int userId) {
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
             if (ps.pkg == null) {
-                PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags);
+                PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags, userId);
                 if (pInfo != null) {
                     return pInfo.applicationInfo;
                 }
@@ -1676,7 +1687,8 @@
         return null;
     }
 
-    private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags) {
+    private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
+            int userId) {
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
             if (ps.pkg == null) {
@@ -1688,15 +1700,16 @@
                 ps.pkg.applicationInfo.dataDir =
                         getDataPathForPackage(ps.pkg.packageName, 0).getPath();
                 ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
-                ps.pkg.mSetEnabled = ps.enabled;
-                ps.pkg.mSetStopped = ps.stopped;
             }
+            ps.pkg.mSetEnabled = ps.getEnabled(userId);
+            ps.pkg.mSetStopped = ps.getStopped(userId);
             return generatePackageInfo(ps.pkg, flags);
         }
         return null;
     }
 
-    public ApplicationInfo getApplicationInfo(String packageName, int flags) {
+    @Override
+    public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
         // writer
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
@@ -1711,7 +1724,7 @@
                 return mAndroidApplication;
             }
             if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
-                return generateApplicationInfoFromSettingsLPw(packageName, flags);
+                return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
             }
         }
         return null;
@@ -1767,16 +1780,13 @@
         });
     }
 
-    public ActivityInfo getActivityInfo(ComponentName component, int flags) {
-        return getActivityInfo(component, flags, Binder.getOrigCallingUser());
-    }
-
-    ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+    @Override
+    public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
 
             if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
-            if (a != null && mSettings.isEnabledLPr(a.info, flags)) {
+            if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
                 return PackageParser.generateActivityInfo(a, flags, userId);
             }
             if (mResolveComponentName.equals(component)) {
@@ -1786,48 +1796,39 @@
         return null;
     }
 
-    public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
-        return getReceiverInfo(component, flags, Binder.getOrigCallingUser());
-    }
-
-    ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
+    @Override
+    public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
         synchronized (mPackages) {
             PackageParser.Activity a = mReceivers.mActivities.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getReceiverInfo " + component + ": " + a);
-            if (a != null && mSettings.isEnabledLPr(a.info, flags)) {
+            if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
                 return PackageParser.generateActivityInfo(a, flags, userId);
             }
         }
         return null;
     }
 
-    public ServiceInfo getServiceInfo(ComponentName component, int flags) {
-        return getServiceInfo(component, flags, Binder.getOrigCallingUser());
-    }
-
-    ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
+    @Override
+    public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         synchronized (mPackages) {
             PackageParser.Service s = mServices.mServices.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getServiceInfo " + component + ": " + s);
-            if (s != null && mSettings.isEnabledLPr(s.info, flags)) {
+            if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
                 return PackageParser.generateServiceInfo(s, flags, userId);
             }
         }
         return null;
     }
 
-    public ProviderInfo getProviderInfo(ComponentName component, int flags) {
-        return getProviderInfo(component, flags, UserId.getUserId(Binder.getCallingUid()));
-    }
-
-    ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
+    @Override
+    public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
         synchronized (mPackages) {
             PackageParser.Provider p = mProvidersByComponent.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getProviderInfo " + component + ": " + p);
-            if (p != null && mSettings.isEnabledLPr(p.info, flags)) {
+            if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
                 return PackageParser.generateProviderInfo(p, flags, userId);
             }
         }
@@ -1872,6 +1873,14 @@
         }
     }
 
+    private void checkValidCaller(int uid, int userId) {
+        if (UserId.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
+            return;
+
+        throw new SecurityException("Caller uid=" + uid
+                + " is not privileged to communicate with user=" + userId);
+    }
+
     public int checkPermission(String permName, String pkgName) {
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(pkgName);
@@ -2006,7 +2015,7 @@
             if (!async) {
                 mSettings.writeLPr();
             } else {
-                scheduleWriteSettingsLocked();            
+                scheduleWriteSettingsLocked();
             }
         }
         return added;
@@ -2241,14 +2250,15 @@
         }
     }
 
+    @Override
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
-            int flags) {
-        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
-        return chooseBestActivity(intent, resolvedType, flags, query);
+            int flags, int userId) {
+        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+        return chooseBestActivity(intent, resolvedType, flags, query, userId);
     }
 
     private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
-                                           int flags, List<ResolveInfo> query) {
+            int flags, List<ResolveInfo> query, int userId) {
         if (query != null) {
             final int N = query.size();
             if (N == 1) {
@@ -2272,7 +2282,7 @@
                 // If we have saved a preference for a preferred activity for
                 // this Intent, use that.
                 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
-                        flags, query, r0.priority);
+                        flags, query, r0.priority, userId);
                 if (ri != null) {
                     return ri;
                 }
@@ -2283,7 +2293,7 @@
     }
 
     ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
-            int flags, List<ResolveInfo> query, int priority) {
+            int flags, List<ResolveInfo> query, int priority, int userId) {
         // writer
         synchronized (mPackages) {
             if (intent.getSelector() != null) {
@@ -2292,7 +2302,7 @@
             if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
             List<PreferredActivity> prefs =
                     mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
-                            (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+                            (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
             if (prefs != null && prefs.size() > 0) {
                 // First figure out how good the original match set is.
                 // We will only allow preferred activities that came
@@ -2326,7 +2336,7 @@
                     if (pa.mPref.mMatch != match) {
                         continue;
                     }
-                    final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags);
+                    final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags, userId);
                     if (DEBUG_PREFERRED) {
                         Log.v(TAG, "Got preferred activity:");
                         if (ai != null) {
@@ -2376,8 +2386,9 @@
         return null;
     }
 
+    @Override
     public List<ResolveInfo> queryIntentActivities(Intent intent,
-            String resolvedType, int flags) {
+            String resolvedType, int flags, int userId) {
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -2388,7 +2399,7 @@
 
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
-            final ActivityInfo ai = getActivityInfo(comp, flags);
+            final ActivityInfo ai = getActivityInfo(comp, flags, userId);
             if (ai != null) {
                 final ResolveInfo ri = new ResolveInfo();
                 ri.activityInfo = ai;
@@ -2401,24 +2412,25 @@
         synchronized (mPackages) {
             final String pkgName = intent.getPackage();
             if (pkgName == null) {
-                return mActivities.queryIntent(intent, resolvedType, flags);
+                return mActivities.queryIntent(intent, resolvedType, flags, userId);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
                 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
-                        pkg.activities);
+                        pkg.activities, userId);
             }
             return new ArrayList<ResolveInfo>();
         }
     }
 
+    @Override
     public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
             Intent[] specifics, String[] specificTypes, Intent intent,
-            String resolvedType, int flags) {
+            String resolvedType, int flags, int userId) {
         final String resultsAction = intent.getAction();
 
         List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
-                | PackageManager.GET_RESOLVED_FILTER);
+                | PackageManager.GET_RESOLVED_FILTER, userId);
 
         if (DEBUG_INTENT_MATCHING) {
             Log.v(TAG, "Query " + intent + ": " + results);
@@ -2461,7 +2473,7 @@
                     ri = resolveIntent(
                         sintent,
                         specificTypes != null ? specificTypes[i] : null,
-                        flags);
+                            flags, userId);
                     if (ri == null) {
                         continue;
                     }
@@ -2472,7 +2484,7 @@
                     comp = new ComponentName(ai.applicationInfo.packageName,
                             ai.name);
                 } else {
-                    ai = getActivityInfo(comp, flags);
+                    ai = getActivityInfo(comp, flags, userId);
                     if (ai == null) {
                         continue;
                     }
@@ -2581,7 +2593,9 @@
         return results;
     }
 
-    public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags) {
+    @Override
+    public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
+            int userId) {
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -2591,7 +2605,7 @@
         }
         if (comp != null) {
             List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
-            ActivityInfo ai = getReceiverInfo(comp, flags);
+            ActivityInfo ai = getReceiverInfo(comp, flags, userId);
             if (ai != null) {
                 ResolveInfo ri = new ResolveInfo();
                 ri.activityInfo = ai;
@@ -2604,18 +2618,20 @@
         synchronized (mPackages) {
             String pkgName = intent.getPackage();
             if (pkgName == null) {
-                return mReceivers.queryIntent(intent, resolvedType, flags);
+                return mReceivers.queryIntent(intent, resolvedType, flags, userId);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers);
+                return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
+                        userId);
             }
             return null;
         }
     }
 
-    public ResolveInfo resolveService(Intent intent, String resolvedType, int flags) {
-        List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags);
+    @Override
+    public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
+        List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
         if (query != null) {
             if (query.size() >= 1) {
                 // If there is more than one service with the same priority,
@@ -2626,7 +2642,9 @@
         return null;
     }
 
-    public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags) {
+    @Override
+    public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
+            int userId) {
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -2636,7 +2654,7 @@
         }
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
-            final ServiceInfo si = getServiceInfo(comp, flags);
+            final ServiceInfo si = getServiceInfo(comp, flags, userId);
             if (si != null) {
                 final ResolveInfo ri = new ResolveInfo();
                 ri.serviceInfo = si;
@@ -2649,11 +2667,12 @@
         synchronized (mPackages) {
             String pkgName = intent.getPackage();
             if (pkgName == null) {
-                return mServices.queryIntent(intent, resolvedType, flags);
+                return mServices.queryIntent(intent, resolvedType, flags, userId);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services);
+                return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
+                        userId);
             }
             return null;
         }
@@ -2678,6 +2697,7 @@
         final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
         final String[] keys;
+        int userId = UserId.getCallingUserId();
 
         // writer
         synchronized (mPackages) {
@@ -2698,7 +2718,7 @@
                 if (listUninstalled) {
                     final PackageSetting ps = mSettings.mPackages.get(packageName);
                     if (ps != null) {
-                        pi = generatePackageInfoFromSettingsLPw(ps.name, flags);
+                        pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
                     }
                 } else {
                     final PackageParser.Package p = mPackages.get(packageName);
@@ -2720,8 +2740,9 @@
         return list;
     }
 
+    @Override
     public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
-            String lastRead) {
+            String lastRead, int userId) {
         final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
         final String[] keys;
@@ -2737,7 +2758,6 @@
             Arrays.sort(keys);
             int i = getContinuationPoint(keys, lastRead);
             final int N = keys.length;
-            final int userId = UserId.getUserId(Binder.getCallingUid());
 
             while (i < N) {
                 final String packageName = keys[i++];
@@ -2746,7 +2766,7 @@
                 if (listUninstalled) {
                     final PackageSetting ps = mSettings.mPackages.get(packageName);
                     if (ps != null) {
-                        ai = generateApplicationInfoFromSettingsLPw(ps.name, flags);
+                        ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
                     }
                 } else {
                     final PackageParser.Package p = mPackages.get(packageName);
@@ -2788,16 +2808,16 @@
         return finalList;
     }
 
-    public ProviderInfo resolveContentProvider(String name, int flags) {
+    @Override
+    public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
         // reader
         synchronized (mPackages) {
             final PackageParser.Provider provider = mProviders.get(name);
             return provider != null
-                    && mSettings.isEnabledLPr(provider.info, flags)
+                    && mSettings.isEnabledLPr(provider.info, flags, userId)
                     && (!mSafeMode || (provider.info.applicationInfo.flags
                             &ApplicationInfo.FLAG_SYSTEM) != 0)
-                    ? PackageParser.generateProviderInfo(provider, flags,
-                            UserId.getUserId(Binder.getCallingUid()))
+                    ? PackageParser.generateProviderInfo(provider, flags, userId)
                     : null;
         }
     }
@@ -2833,15 +2853,15 @@
         // reader
         synchronized (mPackages) {
             final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
-            final int userId = UserId.getUserId(Binder.getCallingUid());
+            final int userId = processName != null ?
+                    UserId.getUserId(uid) : UserId.getCallingUserId();
             while (i.hasNext()) {
                 final PackageParser.Provider p = i.next();
                 if (p.info.authority != null
                         && (processName == null
                                 || (p.info.processName.equals(processName)
-                                        && UserId.getAppId(p.info.applicationInfo.uid)
-                                            == UserId.getAppId(uid)))
-                        && mSettings.isEnabledLPr(p.info, flags)
+                                        && UserId.isSameApp(p.info.applicationInfo.uid, uid)))
+                        && mSettings.isEnabledLPr(p.info, flags, userId)
                         && (!mSafeMode
                                 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
                     if (finalList == null) {
@@ -3491,7 +3511,7 @@
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
 
-            pkg.applicationInfo.uid = pkgSetting.userId;
+            pkg.applicationInfo.uid = pkgSetting.uid;
             pkg.mExtras = pkgSetting;
 
             if (!verifySignaturesLP(pkgSetting, pkg)) {
@@ -4489,19 +4509,20 @@
     private final class ActivityIntentResolver
             extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly) {
+                boolean defaultOnly, int userId) {
             mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly);
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
         }
 
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags) {
+        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+                int userId) {
             mFlags = flags;
             return super.queryIntent(intent, resolvedType,
-                (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
         }
 
         public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                int flags, ArrayList<PackageParser.Activity> packageActivities) {
+                int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
             if (packageActivities == null) {
                 return null;
             }
@@ -4518,7 +4539,7 @@
                     listCut.add(intentFilters);
                 }
             }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
         }
 
         public final void addActivity(PackageParser.Activity a, String type) {
@@ -4583,7 +4604,7 @@
         }
 
         @Override
-        protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter) {
+        protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
             PackageParser.Package p = filter.activity.owner;
             if (p != null) {
                 PackageSetting ps = (PackageSetting)p.mExtras;
@@ -4591,7 +4612,7 @@
                     // System apps are never considered stopped for purposes of
                     // filtering, because there may be no way for the user to
                     // actually re-launch them.
-                    return ps.stopped && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
+                    return ps.getStopped(userId) && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
                 }
             }
             return false;
@@ -4604,8 +4625,8 @@
         
         @Override
         protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
-                int match) {
-            if (!mSettings.isEnabledLPr(info.activity.info, mFlags)) {
+                int match, int userId) {
+            if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
                 return null;
             }
             final PackageParser.Activity activity = info.activity;
@@ -4614,8 +4635,7 @@
                 return null;
             }
             final ResolveInfo res = new ResolveInfo();
-            res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags,
-                    Binder.getOrigCallingUser());
+            res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags, userId);
             if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
                 res.filter = info;
             }
@@ -4669,19 +4689,20 @@
     private final class ServiceIntentResolver
             extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly) {
+                boolean defaultOnly, int userId) {
             mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly);
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
         }
 
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags) {
+        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+                int userId) {
             mFlags = flags;
             return super.queryIntent(intent, resolvedType,
-                (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
         }
 
         public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                int flags, ArrayList<PackageParser.Service> packageServices) {
+                int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
             if (packageServices == null) {
                 return null;
             }
@@ -4698,7 +4719,7 @@
                     listCut.add(intentFilters);
                 }
             }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
         }
 
         public final void addService(PackageParser.Service s) {
@@ -4758,7 +4779,7 @@
         }
 
         @Override
-        protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter) {
+        protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
             PackageParser.Package p = filter.service.owner;
             if (p != null) {
                 PackageSetting ps = (PackageSetting)p.mExtras;
@@ -4766,7 +4787,8 @@
                     // System apps are never considered stopped for purposes of
                     // filtering, because there may be no way for the user to
                     // actually re-launch them.
-                    return ps.stopped && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
+                    return ps.getStopped(userId)
+                            && (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0;
                 }
             }
             return false;
@@ -4779,9 +4801,9 @@
         
         @Override
         protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
-                int match) {
+                int match, int userId) {
             final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
-            if (!mSettings.isEnabledLPr(info.service.info, mFlags)) {
+            if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
                 return null;
             }
             final PackageParser.Service service = info.service;
@@ -4790,8 +4812,7 @@
                 return null;
             }
             final ResolveInfo res = new ResolveInfo();
-            res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags,
-                    Binder.getOrigCallingUser());
+            res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags, userId);
             if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
                 res.filter = filter;
             }
@@ -5644,14 +5665,14 @@
                  * do, then we'll defer to them to verify the packages.
                  */
                 final int requiredUid = mRequiredVerifierPackage == null ? -1
-                        : getPackageUid(mRequiredVerifierPackage);
+                        : getPackageUid(mRequiredVerifierPackage, 0);
                 if (requiredUid != -1 && isVerificationEnabled()) {
                     final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
                     verification.setDataAndType(packageURI, PACKAGE_MIME_TYPE);
                     verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
                     final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
-                            PackageManager.GET_DISABLED_COMPONENTS);
+                            PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
 
                     if (DEBUG_VERIFY) {
                         Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
@@ -7325,17 +7346,19 @@
         return ret;
     }
 
+    @Override
     public void clearApplicationUserData(final String packageName,
-            final IPackageDataObserver observer) {
+            final IPackageDataObserver observer, final int userId) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
+        checkValidCaller(Binder.getCallingUid(), userId);
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
                 final boolean succeeded;
                 synchronized (mInstallLock) {
-                    succeeded = clearApplicationUserDataLI(packageName);
+                    succeeded = clearApplicationUserDataLI(packageName, userId);
                 }
                 if (succeeded) {
                     // invoke DeviceStorageMonitor's update method to clear any notifications
@@ -7356,7 +7379,7 @@
         });
     }
 
-    private boolean clearApplicationUserDataLI(String packageName) {
+    private boolean clearApplicationUserDataLI(String packageName, int userId) {
         if (packageName == null) {
             Slog.w(TAG, "Attempt to delete null packageName.");
             return false;
@@ -7388,7 +7411,7 @@
                 return false;
             }
         }
-        int retCode = mInstaller.clearUserData(packageName, 0); // TODO - correct userId
+        int retCode = mInstaller.clearUserData(packageName, userId);
         if (retCode < 0) {
             Slog.w(TAG, "Couldn't remove cache files for package: "
                     + packageName);
@@ -7402,12 +7425,13 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_CACHE_FILES, null);
         // Queue up an async operation since the package deletion may take a little while.
+        final int userId = UserId.getCallingUserId();
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
                 final boolean succeded;
                 synchronized (mInstallLock) {
-                    succeded = deleteApplicationCacheFilesLI(packageName);
+                    succeded = deleteApplicationCacheFilesLI(packageName, userId);
                 }
                 if(observer != null) {
                     try {
@@ -7420,7 +7444,7 @@
         });
     }
 
-    private boolean deleteApplicationCacheFilesLI(String packageName) {
+    private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
         if (packageName == null) {
             Slog.w(TAG, "Attempt to delete null packageName.");
             return false;
@@ -7438,6 +7462,7 @@
             Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
             return false;
         }
+        // TODO: Pass userId to deleteCacheFiles
         int retCode = mInstaller.deleteCacheFiles(packageName);
         if (retCode < 0) {
             Slog.w(TAG, "Couldn't remove cache files for package: "
@@ -7704,19 +7729,21 @@
         return num;
     }
 
+    @Override
     public void setApplicationEnabledSetting(String appPackageName,
-            int newState, int flags) {
-        setEnabledSetting(appPackageName, null, newState, flags);
+            int newState, int flags, int userId) {
+        setEnabledSetting(appPackageName, null, newState, flags, userId);
     }
 
+    @Override
     public void setComponentEnabledSetting(ComponentName componentName,
-            int newState, int flags) {
+            int newState, int flags, int userId) {
         setEnabledSetting(componentName.getPackageName(),
-                componentName.getClassName(), newState, flags);
+                componentName.getClassName(), newState, flags, userId);
     }
 
     private void setEnabledSetting(
-            final String packageName, String className, int newState, final int flags) {
+            final String packageName, String className, int newState, final int flags, int userId) {
         if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
               || newState == COMPONENT_ENABLED_STATE_ENABLED
               || newState == COMPONENT_ENABLED_STATE_DISABLED
@@ -7728,6 +7755,7 @@
         final int uid = Binder.getCallingUid();
         final int permission = mContext.checkCallingPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+        checkValidCaller(uid, userId);
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
         boolean sendNow = false;
         boolean isApp = (className == null);
@@ -7747,19 +7775,20 @@
                         "Unknown component: " + packageName
                         + "/" + className);
             }
-            if (!allowedByPermission && (!UserId.isSameApp(uid, pkgSetting.userId))) {
+            // Allow root and verify that userId is not being specified by a different user
+            if (!allowedByPermission && !UserId.isSameApp(uid, pkgSetting.uid)) {
                 throw new SecurityException(
                         "Permission Denial: attempt to change component state from pid="
                         + Binder.getCallingPid()
-                        + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
+                        + ", uid=" + uid + ", package uid=" + pkgSetting.uid);
             }
             if (className == null) {
                 // We're dealing with an application/package level state change
-                if (pkgSetting.enabled == newState) {
+                if (pkgSetting.getEnabled(userId) == newState) {
                     // Nothing to do
                     return;
                 }
-                pkgSetting.enabled = newState;
+                pkgSetting.setEnabled(newState, userId);
                 pkgSetting.pkg.mSetEnabled = newState;
             } else {
                 // We're dealing with a component level state change
@@ -7776,17 +7805,17 @@
                 }
                 switch (newState) {
                 case COMPONENT_ENABLED_STATE_ENABLED:
-                    if (!pkgSetting.enableComponentLPw(className)) {
+                    if (!pkgSetting.enableComponentLPw(className, userId)) {
                         return;
                     }
                     break;
                 case COMPONENT_ENABLED_STATE_DISABLED:
-                    if (!pkgSetting.disableComponentLPw(className)) {
+                    if (!pkgSetting.disableComponentLPw(className, userId)) {
                         return;
                     }
                     break;
                 case COMPONENT_ENABLED_STATE_DEFAULT:
-                    if (!pkgSetting.restoreComponentLPw(className)) {
+                    if (!pkgSetting.restoreComponentLPw(className, userId)) {
                         return;
                     }
                     break;
@@ -7795,8 +7824,8 @@
                     return;
                 }
             }
-            mSettings.writeLPr();
-            packageUid = pkgSetting.userId;
+            mSettings.writePackageRestrictionsLPr(userId);
+            packageUid = pkgSetting.uid;
             components = mPendingBroadcasts.get(packageName);
             final boolean newPackage = components == null;
             if (newPackage) {
@@ -7847,16 +7876,17 @@
         sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED,  packageName, extras, null, null);
     }
 
-    public void setPackageStoppedState(String packageName, boolean stopped) {
+    public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
         final int uid = Binder.getCallingUid();
         final int permission = mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+        checkValidCaller(uid, userId);
         // writer
         synchronized (mPackages) {
             if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
-                    uid)) {
-                scheduleWriteStoppedPackagesLocked();
+                    uid, userId)) {
+                scheduleWritePackageRestrictionsLocked(userId);
             }
         }
     }
@@ -7868,17 +7898,23 @@
         }
     }
 
-    public int getApplicationEnabledSetting(String packageName) {
+    @Override
+    public int getApplicationEnabledSetting(String packageName, int userId) {
+        int uid = Binder.getCallingUid();
+        checkValidCaller(uid, userId);
         // reader
         synchronized (mPackages) {
-            return mSettings.getApplicationEnabledSettingLPr(packageName);
+            return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
         }
     }
 
-    public int getComponentEnabledSetting(ComponentName componentName) {
+    @Override
+    public int getComponentEnabledSetting(ComponentName componentName, int userId) {
+        int uid = Binder.getCallingUid();
+        checkValidCaller(uid, userId);
         // reader
         synchronized (mPackages) {
-            return mSettings.getComponentEnabledSettingLPr(componentName);
+            return mSettings.getComponentEnabledSettingLPr(componentName, userId);
         }
     }
 
@@ -8082,7 +8118,7 @@
                 pw.print("  Required: ");
                 pw.print(mRequiredVerifierPackage);
                 pw.print(" (uid=");
-                pw.print(getPackageUid(mRequiredVerifierPackage));
+                pw.print(getPackageUid(mRequiredVerifierPackage, 0));
                 pw.println(")");
             }
 
@@ -8347,7 +8383,7 @@
                                     + " at code path: " + ps.codePathString);
                         // We do have a valid package installed on sdcard
                         processCids.put(args, ps.codePathString);
-                        int uid = ps.userId;
+                        int uid = ps.uid;
                         if (uid != -1) {
                             uidList[num++] = uid;
                         }
diff --git a/services/java/com/android/server/pm/PackageSetting.java b/services/java/com/android/server/pm/PackageSetting.java
index efdc2b3..48ed9bf 100644
--- a/services/java/com/android/server/pm/PackageSetting.java
+++ b/services/java/com/android/server/pm/PackageSetting.java
@@ -24,7 +24,7 @@
  * Settings data for a particular package we know about.
  */
 final class PackageSetting extends PackageSettingBase {
-    int userId;
+    int uid;
     PackageParser.Package pkg;
     SharedUserSetting sharedUser;
 
@@ -41,7 +41,7 @@
     PackageSetting(PackageSetting orig) {
         super(orig);
 
-        userId = orig.userId;
+        uid = orig.uid;
         pkg = orig.pkg;
         sharedUser = orig.sharedUser;
     }
@@ -50,6 +50,6 @@
     public String toString() {
         return "PackageSetting{"
             + Integer.toHexString(System.identityHashCode(this))
-            + " " + name + "/" + userId + "}";
+            + " " + name + "/" + uid + "}";
     }
 }
\ No newline at end of file
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index e2f83ad..b7cf8d6 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -20,6 +20,8 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
+import android.util.SparseArray;
+import android.util.SparseIntArray;
 
 import java.io.File;
 import java.util.HashSet;
@@ -62,20 +64,22 @@
 
     // Whether this package is currently stopped, thus can not be
     // started until explicitly launched by the user.
-    public boolean stopped;
+    private SparseArray<Boolean> stopped = new SparseArray<Boolean>();
 
     // Set to true if we have never launched this app.
-    public boolean notLaunched;
+    private SparseArray<Boolean> notLaunched = new SparseArray<Boolean>();
 
     /* Explicitly disabled components */
-    HashSet<String> disabledComponents = new HashSet<String>(0);
+    private SparseArray<HashSet<String>> disabledComponents = new SparseArray<HashSet<String>>();
     /* Explicitly enabled components */
-    HashSet<String> enabledComponents = new HashSet<String>(0);
-    int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+    private SparseArray<HashSet<String>> enabledComponents = new SparseArray<HashSet<String>>();
+    /* Enabled state */
+    private SparseIntArray enabled = new SparseIntArray();
+
     int installStatus = PKG_INSTALL_COMPLETE;
 
     PackageSettingBase origPackage;
-    
+
     /* package name of the app that installed this package */
     String installerPackageName;
     PackageSettingBase(String name, String realName, File codePath, File resourcePath,
@@ -111,14 +115,12 @@
 
         permissionsFixed = base.permissionsFixed;
         haveGids = base.haveGids;
-        stopped = base.stopped;
         notLaunched = base.notLaunched;
 
-        disabledComponents = (HashSet<String>) base.disabledComponents.clone();
-
-        enabledComponents = (HashSet<String>) base.enabledComponents.clone();
-
-        enabled = base.enabled;
+        disabledComponents = (SparseArray<HashSet<String>>) base.disabledComponents.clone();
+        enabledComponents = (SparseArray<HashSet<String>>) base.enabledComponents.clone();
+        enabled = (SparseIntArray) base.enabled.clone();
+        stopped = (SparseArray<Boolean>) base.stopped.clone();
         installStatus = base.installStatus;
 
         origPackage = base.origPackage;
@@ -177,31 +179,98 @@
         installStatus = base.installStatus;
     }
 
-    boolean enableComponentLPw(String componentClassName) {
-        boolean changed = disabledComponents.remove(componentClassName);
-        changed |= enabledComponents.add(componentClassName);
+    void setEnabled(int state, int userId) {
+        enabled.put(userId, state);
+    }
+
+    int getEnabled(int userId) {
+        return enabled.get(userId, COMPONENT_ENABLED_STATE_DEFAULT);
+    }
+
+    boolean getStopped(int userId) {
+        return stopped.get(userId, false);
+    }
+
+    void setStopped(boolean stop, int userId) {
+        stopped.put(userId, stop);
+    }
+
+    boolean getNotLaunched(int userId) {
+        return notLaunched.get(userId, false);
+    }
+
+    void setNotLaunched(boolean stop, int userId) {
+        notLaunched.put(userId, stop);
+    }
+
+    HashSet<String> getEnabledComponents(int userId) {
+        return getComponentHashSet(enabledComponents, userId);
+    }
+
+    HashSet<String> getDisabledComponents(int userId) {
+        return getComponentHashSet(disabledComponents, userId);
+    }
+
+    void setEnabledComponents(HashSet<String> components, int userId) {
+        enabledComponents.put(userId, components);
+    }
+
+    void setDisabledComponents(HashSet<String> components, int userId) {
+        disabledComponents.put(userId, components);
+    }
+
+    private HashSet<String> getComponentHashSet(SparseArray<HashSet<String>> setArray, int userId) {
+        HashSet<String> set = setArray.get(userId);
+        if (set == null) {
+            set = new HashSet<String>(1);
+            setArray.put(userId, set);
+        }
+        return set;
+    }
+
+    void addDisabledComponent(String componentClassName, int userId) {
+        HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+        disabled.add(componentClassName);
+    }
+
+    void addEnabledComponent(String componentClassName, int userId) {
+        HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+        enabled.add(componentClassName);
+    }
+
+    boolean enableComponentLPw(String componentClassName, int userId) {
+        HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+        HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+        boolean changed = disabled.remove(componentClassName);
+        changed |= enabled.add(componentClassName);
         return changed;
     }
 
-    boolean disableComponentLPw(String componentClassName) {
-        boolean changed = enabledComponents.remove(componentClassName);
-        changed |= disabledComponents.add(componentClassName);
+    boolean disableComponentLPw(String componentClassName, int userId) {
+        HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+        HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+        boolean changed = enabled.remove(componentClassName);
+        changed |= disabled.add(componentClassName);
         return changed;
     }
 
-    boolean restoreComponentLPw(String componentClassName) {
-        boolean changed = enabledComponents.remove(componentClassName);
-        changed |= disabledComponents.remove(componentClassName);
+    boolean restoreComponentLPw(String componentClassName, int userId) {
+        HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+        HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+        boolean changed = enabled.remove(componentClassName);
+        changed |= disabled.remove(componentClassName);
         return changed;
     }
 
-    int getCurrentEnabledStateLPr(String componentName) {
-        if (enabledComponents.contains(componentName)) {
+    int getCurrentEnabledStateLPr(String componentName, int userId) {
+        HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
+        HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
+        if (enabled.contains(componentName)) {
             return COMPONENT_ENABLED_STATE_ENABLED;
-        } else if (disabledComponents.contains(componentName)) {
+        } else if (disabled.contains(componentName)) {
             return COMPONENT_ENABLED_STATE_DISABLED;
         } else {
             return COMPONENT_ENABLED_STATE_DEFAULT;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 363d020..b541c8c 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -32,6 +32,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -40,11 +41,14 @@
 import android.content.pm.PackageParser;
 import android.content.pm.PermissionInfo;
 import android.content.pm.Signature;
+import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserId;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -63,6 +67,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import libcore.io.IoUtils;
@@ -78,6 +83,17 @@
     private static final String TAG_READ_EXTERNAL_STORAGE = "read-external-storage";
     private static final String ATTR_ENFORCEMENT = "enforcement";
 
+    private static final String TAG_ITEM = "item";
+    private static final String TAG_DISABLED_COMPONENTS = "disabled-components";
+    private static final String TAG_ENABLED_COMPONENTS = "enabled-components";
+    private static final String TAG_PACKAGE_RESTRICTIONS = "package-restrictions";
+    private static final String TAG_PACKAGE = "pkg";
+
+    private static final String ATTR_NAME = "name";
+    private static final String ATTR_NOT_LAUNCHED = "nl";
+    private static final String ATTR_ENABLED = "enabled";
+    private static final String ATTR_STOPPED = "stopped";
+
     private final File mSettingsFilename;
     private final File mBackupSettingsFilename;
     private final File mPackageListFilename;
@@ -153,19 +169,24 @@
      */
     private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
 
+    private final File mSystemDir;
     Settings() {
-        File dataDir = Environment.getDataDirectory();
-        File systemDir = new File(dataDir, "system");
-        systemDir.mkdirs();
-        FileUtils.setPermissions(systemDir.toString(),
+        this(Environment.getDataDirectory());
+    }
+
+    Settings(File dataDir) {
+        mSystemDir = new File(dataDir, "system");
+        mSystemDir.mkdirs();
+        FileUtils.setPermissions(mSystemDir.toString(),
                 FileUtils.S_IRWXU|FileUtils.S_IRWXG
                 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                 -1, -1);
-        mSettingsFilename = new File(systemDir, "packages.xml");
-        mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
-        mPackageListFilename = new File(systemDir, "packages.list");
-        mStoppedPackagesFilename = new File(systemDir, "packages-stopped.xml");
-        mBackupStoppedPackagesFilename = new File(systemDir, "packages-stopped-backup.xml");
+        mSettingsFilename = new File(mSystemDir, "packages.xml");
+        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
+        mPackageListFilename = new File(mSystemDir, "packages.list");
+        // Deprecated: Needed for migration
+        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
+        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
     }
 
     PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
@@ -254,7 +275,7 @@
             p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
         }
         PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
-                p.nativeLibraryPathString, p.userId, p.versionCode, p.pkgFlags);
+                p.nativeLibraryPathString, p.uid, p.versionCode, p.pkgFlags);
         mDisabledSysPackages.remove(name);
         return ret;
     }
@@ -263,7 +284,7 @@
             String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
-            if (p.userId == uid) {
+            if (p.uid == uid) {
                 return p;
             }
             PackageManagerService.reportSettingsProblem(Log.ERROR,
@@ -272,7 +293,7 @@
         }
         p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString,
                 vc, pkgFlags);
-        p.userId = uid;
+        p.uid = uid;
         if (addUserIdLPw(uid, p, name)) {
             mPackages.put(name, p);
             return p;
@@ -323,7 +344,7 @@
             }
         }
     }
-    
+
     private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
             String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {
@@ -335,13 +356,13 @@
                     // This is an updated system app with versions in both system
                     // and data partition. Just let the most recent version
                     // take precedence.
-                    Slog.w(PackageManagerService.TAG, "Trying to update system app code path from " +
-                            p.codePathString + " to " + codePath.toString());
+                    Slog.w(PackageManagerService.TAG, "Trying to update system app code path from "
+                            + p.codePathString + " to " + codePath.toString());
                 } else {
                     // Just a change in the code path is not an issue, but
                     // let's log a message about it.
-                    Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from " + p.codePath
-                            + " to " + codePath + "; Retaining data and using new");
+                    Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from "
+                            + p.codePath + " to " + codePath + "; Retaining data and using new");
                     /*
                      * Since we've changed paths, we need to prefer the new
                      * native library path over the one stored in the
@@ -378,15 +399,15 @@
                 // We are consuming the data from an existing package.
                 p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
                         nativeLibraryPathString, vc, pkgFlags);
-                if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + name
-                        + " is adopting original package " + origPackage.name);
+                if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
+                        + name + " is adopting original package " + origPackage.name);
                 // Note that we will retain the new package's signature so
                 // that we can keep its data.
                 PackageSignatures s = p.signatures;
                 p.copyFrom(origPackage);
                 p.signatures = s;
                 p.sharedUser = origPackage.sharedUser;
-                p.userId = origPackage.userId;
+                p.uid = origPackage.uid;
                 p.origPackage = origPackage;
                 mRenamedPackages.put(name, origPackage.name);
                 name = origPackage.name;
@@ -404,11 +425,17 @@
                         e.fillInStackTrace();
                         Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
                     }
-                    p.stopped = true;
-                    p.notLaunched = true;
+                    List<UserInfo> users = getAllUsers();
+                    if (users != null) {
+                        for (UserInfo user : users) {
+                            p.setStopped(true, user.id);
+                            p.setNotLaunched(true, user.id);
+                            writePackageRestrictionsLPr(user.id);
+                        }
+                    }
                 }
                 if (sharedUser != null) {
-                    p.userId = sharedUser.userId;
+                    p.uid = sharedUser.userId;
                 } else {
                     // Clone the setting here for disabled system packages
                     PackageSetting dis = mDisabledSysPackages.get(name);
@@ -420,21 +447,31 @@
                         if (dis.signatures.mSignatures != null) {
                             p.signatures.mSignatures = dis.signatures.mSignatures.clone();
                         }
-                        p.userId = dis.userId;
+                        p.uid = dis.uid;
                         // Clone permissions
                         p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
                         // Clone component info
-                        p.disabledComponents = new HashSet<String>(dis.disabledComponents);
-                        p.enabledComponents = new HashSet<String>(dis.enabledComponents);
+                        List<UserInfo> users = getAllUsers();
+                        if (users != null) {
+                            for (UserInfo user : users) {
+                                int userId = user.id;
+                                p.setDisabledComponents(
+                                        new HashSet<String>(dis.getDisabledComponents(userId)),
+                                        userId);
+                                p.setEnabledComponents(
+                                        new HashSet<String>(dis.getEnabledComponents(userId)),
+                                        userId);
+                            }
+                        }
                         // Add new setting to list of user ids
-                        addUserIdLPw(p.userId, p, name);
+                        addUserIdLPw(p.uid, p, name);
                     } else {
                         // Assign new user id
-                        p.userId = newUserIdLPw(p);
+                        p.uid = newUserIdLPw(p);
                     }
                 }
             }
-            if (p.userId < 0) {
+            if (p.uid < 0) {
                 PackageManagerService.reportSettingsProblem(Log.WARN,
                         "Package " + name + " could not be assigned a valid uid");
                 return null;
@@ -450,8 +487,8 @@
 
     void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
         p.pkg = pkg;
-        pkg.mSetEnabled = p.enabled;
-        pkg.mSetStopped = p.stopped;
+        // pkg.mSetEnabled = p.getEnabled(userId);
+        // pkg.mSetStopped = p.getStopped(userId);
         final String codePath = pkg.applicationInfo.sourceDir;
         final String resourcePath = pkg.applicationInfo.publicSourceDir;
         // Update code path if needed
@@ -475,18 +512,18 @@
             p.nativeLibraryPathString = nativeLibraryPath;
         }
         // Update version code if needed
-         if (pkg.mVersionCode != p.versionCode) {
+        if (pkg.mVersionCode != p.versionCode) {
             p.versionCode = pkg.mVersionCode;
         }
-         // Update signatures if needed.
-         if (p.signatures.mSignatures == null) {
-             p.signatures.assignSignatures(pkg.mSignatures);
-         }
-         // If this app defines a shared user id initialize
-         // the shared user signatures as well.
-         if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
-             p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
-         }
+        // Update signatures if needed.
+        if (p.signatures.mSignatures == null) {
+            p.signatures.assignSignatures(pkg.mSignatures);
+        }
+        // If this app defines a shared user id initialize
+        // the shared user signatures as well.
+        if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
+            p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
+        }
         addPackageSettingLPw(p, pkg.packageName, p.sharedUser);
     }
 
@@ -502,9 +539,9 @@
                         + p.sharedUser + " but is now " + sharedUser
                         + "; I am not changing its files so it will probably fail!");
                 p.sharedUser.packages.remove(p);
-            } else if (p.userId != sharedUser.userId) {
+            } else if (p.uid != sharedUser.userId) {
                 PackageManagerService.reportSettingsProblem(Log.ERROR,
-                    "Package " + p.name + " was user id " + p.userId
+                    "Package " + p.name + " was user id " + p.uid
                     + " but is now user " + sharedUser
                     + " with id " + sharedUser.userId
                     + "; I am not changing its files so it will probably fail!");
@@ -512,7 +549,7 @@
 
             sharedUser.packages.add(p);
             p.sharedUser = sharedUser;
-            p.userId = sharedUser.userId;
+            p.uid = sharedUser.userId;
         }
     }
 
@@ -577,8 +614,8 @@
                     return p.sharedUser.userId;
                 }
             } else {
-                removeUserIdLPw(p.userId);
-                return p.userId;
+                removeUserIdLPw(p.uid);
+                return p.uid;
             }
         }
         return -1;
@@ -591,7 +628,7 @@
                 p.sharedUser.packages.remove(p);
                 p.sharedUser.packages.add(newp);
             } else {
-                replaceUserIdLPw(p.userId, newp);
+                replaceUserIdLPw(p.uid, newp);
             }
         }
         mPackages.put(name, newp);
@@ -658,50 +695,269 @@
         }
     }
 
-    void writeStoppedLPr() {
+    private File getUserPackagesStateFile(int userId) {
+        return new File(mSystemDir,
+                "users/" + userId + "/package-restrictions.xml");
+    }
+
+    private File getUserPackagesStateBackupFile(int userId) {
+        return new File(mSystemDir,
+                "users/" + userId + "/package-restrictions-backup.xml");
+    }
+
+    void writeAllUsersPackageRestrictionsLPr() {
+        List<UserInfo> users = getAllUsers();
+        if (users == null) return;
+
+        for (UserInfo user : users) {
+            writePackageRestrictionsLPr(user.id);
+        }
+    }
+
+    void readAllUsersPackageRestrictionsLPr() {
+        List<UserInfo> users = getAllUsers();
+        if (users == null) {
+            readPackageRestrictionsLPr(0);
+            return;
+        }
+
+        for (UserInfo user : users) {
+            readPackageRestrictionsLPr(user.id);
+        }
+    }
+
+    void readPackageRestrictionsLPr(int userId) {
+        FileInputStream str = null;
+        File userPackagesStateFile = getUserPackagesStateFile(userId);
+        File backupFile = getUserPackagesStateBackupFile(userId);
+        if (backupFile.exists()) {
+            try {
+                str = new FileInputStream(backupFile);
+                mReadMessages.append("Reading from backup stopped packages file\n");
+                PackageManagerService.reportSettingsProblem(Log.INFO,
+                        "Need to read from backup stopped packages file");
+                if (userPackagesStateFile.exists()) {
+                    // If both the backup and normal file exist, we
+                    // ignore the normal one since it might have been
+                    // corrupted.
+                    Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
+                            + userPackagesStateFile);
+                    userPackagesStateFile.delete();
+                }
+            } catch (java.io.IOException e) {
+                // We'll try for the normal settings file.
+            }
+        }
+
+        try {
+            if (str == null) {
+                if (!userPackagesStateFile.exists()) {
+                    mReadMessages.append("No stopped packages file found\n");
+                    PackageManagerService.reportSettingsProblem(Log.INFO,
+                            "No stopped packages file; "
+                            + "assuming all started");
+                    // At first boot, make sure no packages are stopped.
+                    // We usually want to have third party apps initialize
+                    // in the stopped state, but not at first boot.
+                    for (PackageSetting pkg : mPackages.values()) {
+                        pkg.setStopped(false, userId);
+                        pkg.setNotLaunched(false, userId);
+                    }
+                    return;
+                }
+                str = new FileInputStream(userPackagesStateFile);
+            }
+            final XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(str, null);
+
+            int type;
+            while ((type=parser.next()) != XmlPullParser.START_TAG
+                       && type != XmlPullParser.END_DOCUMENT) {
+                ;
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                mReadMessages.append("No start tag found in package restrictions file\n");
+                PackageManagerService.reportSettingsProblem(Log.WARN,
+                        "No start tag found in package manager stopped packages");
+                return;
+            }
+
+            int outerDepth = parser.getDepth();
+            PackageSetting ps = null;
+            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+                   && (type != XmlPullParser.END_TAG
+                           || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG
+                        || type == XmlPullParser.TEXT) {
+                    continue;
+                }
+
+                String tagName = parser.getName();
+                if (tagName.equals(TAG_PACKAGE)) {
+                    String name = parser.getAttributeValue(null, ATTR_NAME);
+                    ps = mPackages.get(name);
+                    if (ps == null) {
+                        Slog.w(PackageManagerService.TAG, "No package known for stopped package: "
+                                + name);
+                        XmlUtils.skipCurrentTag(parser);
+                        continue;
+                    }
+                    String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
+                    int enabled = enabledStr == null ? COMPONENT_ENABLED_STATE_DEFAULT
+                            : Integer.parseInt(enabledStr);
+                    ps.setEnabled(enabled, userId);
+                    String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
+                    boolean stopped = stoppedStr == null ? false : Boolean.parseBoolean(stoppedStr);
+                    ps.setStopped(stopped, userId);
+                    String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
+                    boolean notLaunched = stoppedStr == null ? false
+                            : Boolean.parseBoolean(notLaunchedStr);
+                    ps.setNotLaunched(notLaunched, userId);
+
+                    int packageDepth = parser.getDepth();
+                    while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+                            && (type != XmlPullParser.END_TAG
+                            || parser.getDepth() > packageDepth)) {
+                        if (type == XmlPullParser.END_TAG
+                                || type == XmlPullParser.TEXT) {
+                            continue;
+                        }
+                        tagName = parser.getName();
+                        if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
+                            HashSet<String> components = readComponentsLPr(parser);
+                            ps.setEnabledComponents(components, userId);
+                        } else if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
+                            HashSet<String> components = readComponentsLPr(parser);
+                            ps.setDisabledComponents(components, userId);
+                        }
+                    }
+                } else {
+                    Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
+                          + parser.getName());
+                    XmlUtils.skipCurrentTag(parser);
+                }
+            }
+
+            str.close();
+
+        } catch (XmlPullParserException e) {
+            mReadMessages.append("Error reading: " + e.toString());
+            PackageManagerService.reportSettingsProblem(Log.ERROR,
+                    "Error reading stopped packages: " + e);
+            Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
+
+        } catch (java.io.IOException e) {
+            mReadMessages.append("Error reading: " + e.toString());
+            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
+            Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
+        }
+    }
+
+    private HashSet<String> readComponentsLPr(XmlPullParser parser)
+            throws IOException, XmlPullParserException {
+        HashSet<String> components = new HashSet<String>();
+        int type;
+        int outerDepth = parser.getDepth();
+        String tagName;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG
+                    || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            tagName = parser.getName();
+            if (tagName.equals(TAG_ITEM)) {
+                String componentName = parser.getAttributeValue(null, ATTR_NAME);
+                if (componentName != null) {
+                    components.add(componentName);
+                }
+            }
+        }
+        return components;
+    }
+
+    void writePackageRestrictionsLPr(int userId) {
         // Keep the old stopped packages around until we know the new ones have
         // been successfully written.
-        if (mStoppedPackagesFilename.exists()) {
+        File userPackagesStateFile = getUserPackagesStateFile(userId);
+        File backupFile = getUserPackagesStateBackupFile(userId);
+        new File(userPackagesStateFile.getParent()).mkdirs();
+        if (userPackagesStateFile.exists()) {
             // Presence of backup settings file indicates that we failed
             // to persist packages earlier. So preserve the older
             // backup for future reference since the current packages
             // might have been corrupted.
-            if (!mBackupStoppedPackagesFilename.exists()) {
-                if (!mStoppedPackagesFilename.renameTo(mBackupStoppedPackagesFilename)) {
-                    Log.wtf(PackageManagerService.TAG, "Unable to backup package manager stopped packages, "
+            if (!backupFile.exists()) {
+                if (!userPackagesStateFile.renameTo(backupFile)) {
+                    Log.wtf(PackageManagerService.TAG, "Unable to backup user packages state file, "
                             + "current changes will be lost at reboot");
                     return;
                 }
             } else {
-                mStoppedPackagesFilename.delete();
+                userPackagesStateFile.delete();
                 Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
             }
         }
 
         try {
-            final FileOutputStream fstr = new FileOutputStream(mStoppedPackagesFilename);
+            final FileOutputStream fstr = new FileOutputStream(userPackagesStateFile);
             final BufferedOutputStream str = new BufferedOutputStream(fstr);
 
-            //XmlSerializer serializer = XmlUtils.serializerInstance();
             final XmlSerializer serializer = new FastXmlSerializer();
             serializer.setOutput(str, "utf-8");
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
-            serializer.startTag(null, "stopped-packages");
+            serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
 
             for (final PackageSetting pkg : mPackages.values()) {
-                if (pkg.stopped) {
-                    serializer.startTag(null, "pkg");
-                    serializer.attribute(null, "name", pkg.name);
-                    if (pkg.notLaunched) {
-                        serializer.attribute(null, "nl", "1");
+                if (pkg.getStopped(userId)
+                        || pkg.getNotLaunched(userId)
+                        || pkg.getEnabled(userId) != COMPONENT_ENABLED_STATE_DEFAULT
+                        || pkg.getEnabledComponents(userId).size() > 0
+                        || pkg.getDisabledComponents(userId).size() > 0) {
+                    serializer.startTag(null, TAG_PACKAGE);
+                    serializer.attribute(null, ATTR_NAME, pkg.name);
+                    boolean stopped = pkg.getStopped(userId);
+                    boolean notLaunched = pkg.getNotLaunched(userId);
+                    int enabled = pkg.getEnabled(userId);
+                    HashSet<String> enabledComponents = pkg.getEnabledComponents(userId);
+                    HashSet<String> disabledComponents = pkg.getDisabledComponents(userId);
+
+                    if (stopped) {
+                        serializer.attribute(null, ATTR_STOPPED, "true");
                     }
-                    serializer.endTag(null, "pkg");
+                    if (notLaunched) {
+                        serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
+                    }
+                    if (enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
+                        serializer.attribute(null, ATTR_ENABLED, Integer.toString(enabled));
+                    }
+                    if (enabledComponents.size() > 0) {
+                        serializer.startTag(null, TAG_ENABLED_COMPONENTS);
+                        for (final String name : enabledComponents) {
+                            serializer.startTag(null, TAG_ITEM);
+                            serializer.attribute(null, ATTR_NAME, name);
+                            serializer.endTag(null, TAG_ITEM);
+                        }
+                        serializer.endTag(null, TAG_ENABLED_COMPONENTS);
+                    }
+                    if (disabledComponents.size() > 0) {
+                        serializer.startTag(null, TAG_DISABLED_COMPONENTS);
+                        for (final String name : disabledComponents) {
+                            serializer.startTag(null, TAG_ITEM);
+                            serializer.attribute(null, ATTR_NAME, name);
+                            serializer.endTag(null, TAG_ITEM);
+                        }
+                        serializer.endTag(null, TAG_DISABLED_COMPONENTS);
+                    }
+                    serializer.endTag(null, TAG_PACKAGE);
                 }
             }
 
-            serializer.endTag(null, "stopped-packages");
+            serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
 
             serializer.endDocument();
 
@@ -711,8 +967,8 @@
 
             // New settings successfully written, old ones are no longer
             // needed.
-            mBackupStoppedPackagesFilename.delete();
-            FileUtils.setPermissions(mStoppedPackagesFilename.toString(),
+            backupFile.delete();
+            FileUtils.setPermissions(userPackagesStateFile.toString(),
                     FileUtils.S_IRUSR|FileUtils.S_IWUSR
                     |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
                     -1, -1);
@@ -720,26 +976,30 @@
             // Done, all is good!
             return;
         } catch(java.io.IOException e) {
-            Log.wtf(PackageManagerService.TAG, "Unable to write package manager stopped packages, "
+            Log.wtf(PackageManagerService.TAG,
+                    "Unable to write package manager user packages state, "
                     + " current changes will be lost at reboot", e);
         }
 
         // Clean up partially written files
-        if (mStoppedPackagesFilename.exists()) {
-            if (!mStoppedPackagesFilename.delete()) {
-                Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: " + mStoppedPackagesFilename);
+        if (userPackagesStateFile.exists()) {
+            if (!userPackagesStateFile.delete()) {
+                Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "
+                        + mStoppedPackagesFilename);
             }
         }
     }
 
     // Note: assumed "stopped" field is already cleared in all packages.
+    // Legacy reader, used to read in the old file format after an upgrade. Not used after that.
     void readStoppedLPw() {
         FileInputStream str = null;
         if (mBackupStoppedPackagesFilename.exists()) {
             try {
                 str = new FileInputStream(mBackupStoppedPackagesFilename);
                 mReadMessages.append("Reading from backup stopped packages file\n");
-                PackageManagerService.reportSettingsProblem(Log.INFO, "Need to read from backup stopped packages file");
+                PackageManagerService.reportSettingsProblem(Log.INFO,
+                        "Need to read from backup stopped packages file");
                 if (mSettingsFilename.exists()) {
                     // If both the backup and normal file exist, we
                     // ignore the normal one since it might have been
@@ -757,14 +1017,14 @@
             if (str == null) {
                 if (!mStoppedPackagesFilename.exists()) {
                     mReadMessages.append("No stopped packages file found\n");
-                    PackageManagerService.reportSettingsProblem(Log.INFO, "No stopped packages file file; "
-                            + "assuming all started");
+                    PackageManagerService.reportSettingsProblem(Log.INFO,
+                            "No stopped packages file file; assuming all started");
                     // At first boot, make sure no packages are stopped.
                     // We usually want to have third party apps initialize
                     // in the stopped state, but not at first boot.
                     for (PackageSetting pkg : mPackages.values()) {
-                        pkg.stopped = false;
-                        pkg.notLaunched = false;
+                        pkg.setStopped(false, 0);
+                        pkg.setNotLaunched(false, 0);
                     }
                     return;
                 }
@@ -796,16 +1056,17 @@
                 }
 
                 String tagName = parser.getName();
-                if (tagName.equals("pkg")) {
-                    String name = parser.getAttributeValue(null, "name");
+                if (tagName.equals(TAG_PACKAGE)) {
+                    String name = parser.getAttributeValue(null, ATTR_NAME);
                     PackageSetting ps = mPackages.get(name);
                     if (ps != null) {
-                        ps.stopped = true;
-                        if ("1".equals(parser.getAttributeValue(null, "nl"))) {
-                            ps.notLaunched = true;
+                        ps.setStopped(true, 0);
+                        if ("1".equals(parser.getAttributeValue(null, ATTR_NOT_LAUNCHED))) {
+                            ps.setNotLaunched(true, 0);
                         }
                     } else {
-                        Slog.w(PackageManagerService.TAG, "No package known for stopped package: " + name);
+                        Slog.w(PackageManagerService.TAG,
+                                "No package known for stopped package: " + name);
                     }
                     XmlUtils.skipCurrentTag(parser);
                 } else {
@@ -817,12 +1078,13 @@
 
             str.close();
 
-        } catch(XmlPullParserException e) {
+        } catch (XmlPullParserException e) {
             mReadMessages.append("Error reading: " + e.toString());
-            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading stopped packages: " + e);
+            PackageManagerService.reportSettingsProblem(Log.ERROR,
+                    "Error reading stopped packages: " + e);
             Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
 
-        } catch(java.io.IOException e) {
+        } catch (java.io.IOException e) {
             mReadMessages.append("Error reading: " + e.toString());
             PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
             Log.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages", e);
@@ -906,23 +1168,23 @@
 
             serializer.startTag(null, "preferred-activities");
             for (final PreferredActivity pa : mPreferredActivities.filterSet()) {
-                serializer.startTag(null, "item");
+                serializer.startTag(null, TAG_ITEM);
                 pa.writeToXml(serializer);
-                serializer.endTag(null, "item");
+                serializer.endTag(null, TAG_ITEM);
             }
             serializer.endTag(null, "preferred-activities");
 
             for (final SharedUserSetting usr : mSharedUsers.values()) {
                 serializer.startTag(null, "shared-user");
-                serializer.attribute(null, "name", usr.name);
+                serializer.attribute(null, ATTR_NAME, usr.name);
                 serializer.attribute(null, "userId",
                         Integer.toString(usr.userId));
                 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
                 serializer.startTag(null, "perms");
                 for (String name : usr.grantedPermissions) {
-                    serializer.startTag(null, "item");
-                    serializer.attribute(null, "name", name);
-                    serializer.endTag(null, "item");
+                    serializer.startTag(null, TAG_ITEM);
+                    serializer.attribute(null, ATTR_NAME, name);
+                    serializer.endTag(null, TAG_ITEM);
                 }
                 serializer.endTag(null, "perms");
                 serializer.endTag(null, "shared-user");
@@ -931,7 +1193,7 @@
             if (mPackagesToBeCleaned.size() > 0) {
                 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
                     serializer.startTag(null, "cleaning-package");
-                    serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
+                    serializer.attribute(null, ATTR_NAME, mPackagesToBeCleaned.get(i));
                     serializer.endTag(null, "cleaning-package");
                 }
             }
@@ -1016,8 +1278,7 @@
                     |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
                     -1, -1);
 
-            writeStoppedLPr();
-
+            writeAllUsersPackageRestrictionsLPr();
             return;
 
         } catch(XmlPullParserException e) {
@@ -1030,7 +1291,8 @@
         // Clean up partially written files
         if (mSettingsFilename.exists()) {
             if (!mSettingsFilename.delete()) {
-                Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: " + mSettingsFilename);
+                Log.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
+                        + mSettingsFilename);
             }
         }
         //Debug.stopMethodTracing();
@@ -1039,7 +1301,7 @@
     void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
             throws java.io.IOException {
         serializer.startTag(null, "updated-package");
-        serializer.attribute(null, "name", pkg.name);
+        serializer.attribute(null, ATTR_NAME, pkg.name);
         if (pkg.realName != null) {
             serializer.attribute(null, "realName", pkg.realName);
         }
@@ -1055,9 +1317,9 @@
             serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
         }
         if (pkg.sharedUser == null) {
-            serializer.attribute(null, "userId", Integer.toString(pkg.userId));
+            serializer.attribute(null, "userId", Integer.toString(pkg.uid));
         } else {
-            serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId));
+            serializer.attribute(null, "sharedUserId", Integer.toString(pkg.uid));
         }
         serializer.startTag(null, "perms");
         if (pkg.sharedUser == null) {
@@ -1072,9 +1334,9 @@
                     // this wont
                     // match the semantics of grantedPermissions. So write all
                     // permissions.
-                    serializer.startTag(null, "item");
-                    serializer.attribute(null, "name", name);
-                    serializer.endTag(null, "item");
+                    serializer.startTag(null, TAG_ITEM);
+                    serializer.attribute(null, ATTR_NAME, name);
+                    serializer.endTag(null, TAG_ITEM);
                 }
             }
         }
@@ -1085,7 +1347,7 @@
     void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg)
             throws java.io.IOException {
         serializer.startTag(null, "package");
-        serializer.attribute(null, "name", pkg.name);
+        serializer.attribute(null, ATTR_NAME, pkg.name);
         if (pkg.realName != null) {
             serializer.attribute(null, "realName", pkg.realName);
         }
@@ -1102,16 +1364,13 @@
         serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
         serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
         if (pkg.sharedUser == null) {
-            serializer.attribute(null, "userId", Integer.toString(pkg.userId));
+            serializer.attribute(null, "userId", Integer.toString(pkg.uid));
         } else {
-            serializer.attribute(null, "sharedUserId", Integer.toString(pkg.userId));
+            serializer.attribute(null, "sharedUserId", Integer.toString(pkg.uid));
         }
         if (pkg.uidError) {
             serializer.attribute(null, "uidError", "true");
         }
-        if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
-            serializer.attribute(null, "enabled", Integer.toString(pkg.enabled));
-        }
         if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
             serializer.attribute(null, "installStatus", "false");
         }
@@ -1127,31 +1386,13 @@
                 // empty permissions list so permissionsFixed will
                 // be set.
                 for (final String name : pkg.grantedPermissions) {
-                    serializer.startTag(null, "item");
-                    serializer.attribute(null, "name", name);
-                    serializer.endTag(null, "item");
+                    serializer.startTag(null, TAG_ITEM);
+                    serializer.attribute(null, ATTR_NAME, name);
+                    serializer.endTag(null, TAG_ITEM);
                 }
             }
             serializer.endTag(null, "perms");
         }
-        if (pkg.disabledComponents.size() > 0) {
-            serializer.startTag(null, "disabled-components");
-            for (final String name : pkg.disabledComponents) {
-                serializer.startTag(null, "item");
-                serializer.attribute(null, "name", name);
-                serializer.endTag(null, "item");
-            }
-            serializer.endTag(null, "disabled-components");
-        }
-        if (pkg.enabledComponents.size() > 0) {
-            serializer.startTag(null, "enabled-components");
-            for (final String name : pkg.enabledComponents) {
-                serializer.startTag(null, "item");
-                serializer.attribute(null, "name", name);
-                serializer.endTag(null, "item");
-            }
-            serializer.endTag(null, "enabled-components");
-        }
 
         serializer.endTag(null, "package");
     }
@@ -1159,8 +1400,8 @@
     void writePermissionLPr(XmlSerializer serializer, BasePermission bp)
             throws XmlPullParserException, java.io.IOException {
         if (bp.type != BasePermission.TYPE_BUILTIN && bp.sourcePackage != null) {
-            serializer.startTag(null, "item");
-            serializer.attribute(null, "name", bp.name);
+            serializer.startTag(null, TAG_ITEM);
+            serializer.attribute(null, ATTR_NAME, bp.name);
             serializer.attribute(null, "package", bp.sourcePackage);
             if (bp.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
                 serializer.attribute(null, "protection", Integer.toString(bp.protectionLevel));
@@ -1180,7 +1421,7 @@
                     }
                 }
             }
-            serializer.endTag(null, "item");
+            serializer.endTag(null, TAG_ITEM);
         }
     }
 
@@ -1198,7 +1439,7 @@
         return ret;
     }
 
-    boolean readLPw() {
+    boolean readLPw(List<UserInfo> users) {
         FileInputStream str = null;
         if (mBackupSettingsFilename.exists()) {
             try {
@@ -1273,7 +1514,7 @@
                 } else if (tagName.equals("updated-package")) {
                     readDisabledSysPackageLPw(parser);
                 } else if (tagName.equals("cleaning-package")) {
-                    String name = parser.getAttributeValue(null, "name");
+                    String name = parser.getAttributeValue(null, ATTR_NAME);
                     if (name != null) {
                         mPackagesToBeCleaned.add(name);
                     }
@@ -1366,14 +1607,29 @@
         final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
         while (disabledIt.hasNext()) {
             final PackageSetting disabledPs = disabledIt.next();
-            final Object id = getUserIdLPr(disabledPs.userId);
+            final Object id = getUserIdLPr(disabledPs.uid);
             if (id != null && id instanceof SharedUserSetting) {
                 disabledPs.sharedUser = (SharedUserSetting) id;
             }
         }
 
-        readStoppedLPw();
-
+        if (mBackupStoppedPackagesFilename.exists()
+                || mStoppedPackagesFilename.exists()) {
+            // Read old file
+            readStoppedLPw();
+            mBackupStoppedPackagesFilename.delete();
+            mStoppedPackagesFilename.delete();
+            // Migrate to new file format
+            writePackageRestrictionsLPr(0);
+        } else {
+            if (users == null) {
+                readPackageRestrictionsLPr(0);
+            } else {
+                for (UserInfo user : users) {
+                    readPackageRestrictionsLPr(user.id);
+                }
+            }
+        }
         mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
                 + mSharedUsers.size() + " shared uids\n");
 
@@ -1407,8 +1663,8 @@
             }
 
             final String tagName = parser.getName();
-            if (tagName.equals("item")) {
-                final String name = parser.getAttributeValue(null, "name");
+            if (tagName.equals(TAG_ITEM)) {
+                final String name = parser.getAttributeValue(null, ATTR_NAME);
                 final String sourcePackage = parser.getAttributeValue(null, "package");
                 final String ptype = parser.getAttributeValue(null, "type");
                 if (name != null && sourcePackage != null) {
@@ -1444,7 +1700,7 @@
 
     private void readDisabledSysPackageLPw(XmlPullParser parser) throws XmlPullParserException,
             IOException {
-        String name = parser.getAttributeValue(null, "name");
+        String name = parser.getAttributeValue(null, ATTR_NAME);
         String realName = parser.getAttributeValue(null, "realName");
         String codePathStr = parser.getAttributeValue(null, "codePath");
         String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
@@ -1497,10 +1753,10 @@
             }
         }
         String idStr = parser.getAttributeValue(null, "userId");
-        ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
-        if (ps.userId <= 0) {
+        ps.uid = idStr != null ? Integer.parseInt(idStr) : 0;
+        if (ps.uid <= 0) {
             String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
-            ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
+            ps.uid = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
         }
         int outerDepth = parser.getDepth();
         int type;
@@ -1541,7 +1797,7 @@
         String version = null;
         int versionCode = 0;
         try {
-            name = parser.getAttributeValue(null, "name");
+            name = parser.getAttributeValue(null, ATTR_NAME);
             realName = parser.getAttributeValue(null, "realName");
             idStr = parser.getAttributeValue(null, "userId");
             uidError = parser.getAttributeValue(null, "uidError");
@@ -1672,17 +1928,18 @@
             packageSetting.uidError = "true".equals(uidError);
             packageSetting.installerPackageName = installerPackageName;
             packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
-            final String enabledStr = parser.getAttributeValue(null, "enabled");
+            // Handle legacy string here for single-user mode
+            final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
             if (enabledStr != null) {
                 try {
-                    packageSetting.enabled = Integer.parseInt(enabledStr);
+                    packageSetting.setEnabled(Integer.parseInt(enabledStr), 0 /* userId */);
                 } catch (NumberFormatException e) {
                     if (enabledStr.equalsIgnoreCase("true")) {
-                        packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
+                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 0);
                     } else if (enabledStr.equalsIgnoreCase("false")) {
-                        packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
+                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0);
                     } else if (enabledStr.equalsIgnoreCase("default")) {
-                        packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+                        packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0);
                     } else {
                         PackageManagerService.reportSettingsProblem(Log.WARN,
                                 "Error in package manager settings: package " + name
@@ -1691,8 +1948,9 @@
                     }
                 }
             } else {
-                packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+                packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0);
             }
+
             final String installStatusStr = parser.getAttributeValue(null, "installStatus");
             if (installStatusStr != null) {
                 if (installStatusStr.equalsIgnoreCase("false")) {
@@ -1711,10 +1969,11 @@
                 }
 
                 String tagName = parser.getName();
-                if (tagName.equals("disabled-components")) {
-                    readDisabledComponentsLPw(packageSetting, parser);
-                } else if (tagName.equals("enabled-components")) {
-                    readEnabledComponentsLPw(packageSetting, parser);
+                // Legacy 
+                if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
+                    readDisabledComponentsLPw(packageSetting, parser, 0);
+                } else if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
+                    readEnabledComponentsLPw(packageSetting, parser, 0);
                 } else if (tagName.equals("sigs")) {
                     packageSetting.signatures.readXml(parser, mPastSignatures);
                 } else if (tagName.equals("perms")) {
@@ -1731,8 +1990,8 @@
         }
     }
 
-    private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser)
-            throws IOException, XmlPullParserException {
+    private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
+            int userId) throws IOException, XmlPullParserException {
         int outerDepth = parser.getDepth();
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1742,10 +2001,10 @@
             }
 
             String tagName = parser.getName();
-            if (tagName.equals("item")) {
-                String name = parser.getAttributeValue(null, "name");
+            if (tagName.equals(TAG_ITEM)) {
+                String name = parser.getAttributeValue(null, ATTR_NAME);
                 if (name != null) {
-                    packageSetting.disabledComponents.add(name.intern());
+                    packageSetting.addDisabledComponent(name.intern(), userId);
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Error in package manager settings: <disabled-components> has"
@@ -1759,8 +2018,8 @@
         }
     }
 
-    private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser)
-            throws IOException, XmlPullParserException {
+    private void readEnabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
+            int userId) throws IOException, XmlPullParserException {
         int outerDepth = parser.getDepth();
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1770,10 +2029,10 @@
             }
 
             String tagName = parser.getName();
-            if (tagName.equals("item")) {
-                String name = parser.getAttributeValue(null, "name");
+            if (tagName.equals(TAG_ITEM)) {
+                String name = parser.getAttributeValue(null, ATTR_NAME);
                 if (name != null) {
-                    packageSetting.enabledComponents.add(name.intern());
+                    packageSetting.addEnabledComponent(name.intern(), userId);
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Error in package manager settings: <enabled-components> has"
@@ -1787,13 +2046,13 @@
         }
     }
 
-    private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
+    private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException,IOException {
         String name = null;
         String idStr = null;
         int pkgFlags = 0;
         SharedUserSetting su = null;
         try {
-            name = parser.getAttributeValue(null, "name");
+            name = parser.getAttributeValue(null, ATTR_NAME);
             idStr = parser.getAttributeValue(null, "userId");
             int userId = idStr != null ? Integer.parseInt(idStr) : 0;
             if ("true".equals(parser.getAttributeValue(null, "system"))) {
@@ -1859,8 +2118,8 @@
             }
 
             String tagName = parser.getName();
-            if (tagName.equals("item")) {
-                String name = parser.getAttributeValue(null, "name");
+            if (tagName.equals(TAG_ITEM)) {
+                String name = parser.getAttributeValue(null, ATTR_NAME);
                 if (name != null) {
                     outPerms.add(name.intern());
                 } else {
@@ -1887,7 +2146,7 @@
             }
 
             String tagName = parser.getName();
-            if (tagName.equals("item")) {
+            if (tagName.equals(TAG_ITEM)) {
                 PreferredActivity pa = new PreferredActivity(parser);
                 if (pa.mPref.getParseError() == null) {
                     mPreferredActivities.addFilter(pa);
@@ -1940,32 +2199,34 @@
         return ps;
     }
 
-    boolean isEnabledLPr(ComponentInfo componentInfo, int flags) {
+    boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
         if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
             return true;
         }
-        final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
+        final String pkgName = componentInfo.packageName;
+        final PackageSetting packageSettings = mPackages.get(pkgName);
         if (PackageManagerService.DEBUG_SETTINGS) {
-            Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = " + componentInfo.packageName
-                       + " componentName = " + componentInfo.name);
+            Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
+                    + componentInfo.packageName + " componentName = " + componentInfo.name);
             Log.v(PackageManagerService.TAG, "enabledComponents: "
-                       + Arrays.toString(packageSettings.enabledComponents.toArray()));
+                    + Arrays.toString(packageSettings.getEnabledComponents(userId).toArray()));
             Log.v(PackageManagerService.TAG, "disabledComponents: "
-                       + Arrays.toString(packageSettings.disabledComponents.toArray()));
+                    + Arrays.toString(packageSettings.getDisabledComponents(userId).toArray()));
         }
         if (packageSettings == null) {
             return false;
         }
-        if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED
-                || packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
+        final int enabled = packageSettings.getEnabled(userId);
+        if (enabled == COMPONENT_ENABLED_STATE_DISABLED
+                || enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
                 || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
-                        && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
+                    && enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
             return false;
         }
-        if (packageSettings.enabledComponents.contains(componentInfo.name)) {
+        if (packageSettings.getEnabledComponents(userId).contains(componentInfo.name)) {
             return true;
         }
-        if (packageSettings.disabledComponents.contains(componentInfo.name)) {
+        if (packageSettings.getDisabledComponents(userId).contains(componentInfo.name)) {
             return false;
         }
         return componentInfo.enabled;
@@ -1979,35 +2240,36 @@
         return pkg.installerPackageName;
     }
 
-    int getApplicationEnabledSettingLPr(String packageName) {
+    int getApplicationEnabledSettingLPr(String packageName, int userId) {
         final PackageSetting pkg = mPackages.get(packageName);
         if (pkg == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        return pkg.enabled;
+        return pkg.getEnabled(userId);
     }
 
-    int getComponentEnabledSettingLPr(ComponentName componentName) {
+    int getComponentEnabledSettingLPr(ComponentName componentName, int userId) {
         final String packageName = componentName.getPackageName();
         final PackageSetting pkg = mPackages.get(packageName);
         if (pkg == null) {
             throw new IllegalArgumentException("Unknown component: " + componentName);
         }
         final String classNameStr = componentName.getClassName();
-        return pkg.getCurrentEnabledStateLPr(classNameStr);
+        return pkg.getCurrentEnabledStateLPr(classNameStr, userId);
     }
-    
+
     boolean setPackageStoppedStateLPw(String packageName, boolean stopped,
-            boolean allowedByPermission, int uid) {
+            boolean allowedByPermission, int uid, int userId) {
+        int appId = UserId.getAppId(uid);
         final PackageSetting pkgSetting = mPackages.get(packageName);
         if (pkgSetting == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        if (!allowedByPermission && (uid != pkgSetting.userId)) {
+        if (!allowedByPermission && (appId != pkgSetting.uid)) {
             throw new SecurityException(
                     "Permission Denial: attempt to change stopped state from pid="
                     + Binder.getCallingPid()
-                    + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
+                    + ", uid=" + uid + ", package uid=" + pkgSetting.uid);
         }
         if (DEBUG_STOPPED) {
             if (stopped) {
@@ -2016,22 +2278,33 @@
                 Slog.i(TAG, "Stopping package " + packageName, e);
             }
         }
-        if (pkgSetting.stopped != stopped) {
-            pkgSetting.stopped = stopped;
-            pkgSetting.pkg.mSetStopped = stopped;
-            if (pkgSetting.notLaunched) {
+        if (pkgSetting.getStopped(userId) != stopped) {
+            pkgSetting.setStopped(stopped, userId);
+            // pkgSetting.pkg.mSetStopped = stopped;
+            if (pkgSetting.getNotLaunched(userId)) {
                 if (pkgSetting.installerPackageName != null) {
                     PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
                             pkgSetting.name, null,
                             pkgSetting.installerPackageName, null);
                 }
-                pkgSetting.notLaunched = false;
+                pkgSetting.setNotLaunched(false, userId);
             }
             return true;
         }
         return false;
     }
 
+    private List<UserInfo> getAllUsers() {
+        try {
+            return AppGlobals.getPackageManager().getUsers();
+        } catch (RemoteException re) {
+            // Local to system process, shouldn't happen
+        } catch (NullPointerException npe) {
+            // packagemanager not yet initialized
+        }
+        return null;
+    }
+
     static final void printFlags(PrintWriter pw, int val, Object[] spec) {
         pw.print("[ ");
         for (int i=0; i<spec.length; i+=2) {
@@ -2096,7 +2369,7 @@
                 pw.println(ps.name);
             }
 
-            pw.print("    userId="); pw.print(ps.userId);
+            pw.print("    userId="); pw.print(ps.uid);
             pw.print(" gids="); pw.println(PackageManagerService.arrayToString(ps.gids));
             pw.print("    sharedUser="); pw.println(ps.sharedUser);
             pw.print("    pkg="); pw.println(ps.pkg);
@@ -2169,18 +2442,24 @@
             pw.print(" haveGids="); pw.println(ps.haveGids);
             pw.print("    pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
             pw.print(" installStatus="); pw.print(ps.installStatus);
-            pw.print(" stopped="); pw.print(ps.stopped);
-            pw.print(" enabled="); pw.println(ps.enabled);
-            if (ps.disabledComponents.size() > 0) {
-                pw.println("    disabledComponents:");
-                for (String s : ps.disabledComponents) {
-                    pw.print("      "); pw.println(s);
+            List<UserInfo> users = getAllUsers();
+            for (UserInfo user : users) {
+                pw.print(" User "); pw.print(user.id); pw.print(": ");
+                pw.print(" stopped=");
+                pw.print(ps.getStopped(user.id));
+                pw.print(" enabled=");
+                pw.println(ps.getEnabled(user.id));
+                if (ps.getDisabledComponents(user.id).size() > 0) {
+                    pw.println("    disabledComponents:");
+                    for (String s : ps.getDisabledComponents(user.id)) {
+                        pw.print("      "); pw.println(s);
+                    }
                 }
-            }
-            if (ps.enabledComponents.size() > 0) {
-                pw.println("    enabledComponents:");
-                for (String s : ps.enabledComponents) {
-                    pw.print("      "); pw.println(s);
+                if (ps.getEnabledComponents(user.id).size() > 0) {
+                    pw.println("    enabledComponents:");
+                    for (String s : ps.getEnabledComponents(user.id)) {
+                        pw.print("      "); pw.println(s);
+                    }
                 }
             }
             if (ps.grantedPermissions.size() > 0) {
@@ -2234,7 +2513,7 @@
                     pw.println(ps.name);
                 }
                 pw.print("    userId=");
-                pw.println(ps.userId);
+                pw.println(ps.uid);
                 pw.print("    sharedUser=");
                 pw.println(ps.sharedUser);
                 pw.print("    codePath=");
@@ -2244,7 +2523,7 @@
             }
         }
     }
-    
+
     void dumpPermissionsLPr(PrintWriter pw, String packageName, DumpState dumpState) {
         boolean printedSomething = false;
         for (BasePermission p : mPermissions.values()) {
diff --git a/services/java/com/android/server/pm/UserManager.java b/services/java/com/android/server/pm/UserManager.java
index 5eacf4a..959e570 100644
--- a/services/java/com/android/server/pm/UserManager.java
+++ b/services/java/com/android/server/pm/UserManager.java
@@ -73,6 +73,9 @@
     UserManager(File dataDir, File baseUserPath) {
         mUsersDir = new File(dataDir, USER_INFO_DIR);
         mUsersDir.mkdirs();
+        // Make zeroth user directory, for services to migrate their files to that location
+        File userZeroDir = new File(mUsersDir, "0");
+        userZeroDir.mkdirs();
         mBaseUserPath = baseUserPath;
         FileUtils.setPermissions(mUsersDir.toString(),
                 FileUtils.S_IRWXU|FileUtils.S_IRWXG
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index ed83fbe..c2ded8a 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -43,6 +43,7 @@
 import android.os.Process;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UEventObserver;
 import android.provider.Settings;
@@ -206,6 +207,9 @@
     }
 
      private static String addFunction(String functions, String function) {
+         if ("none".equals(functions)) {
+             return function;
+         }
         if (!containsFunction(functions, function)) {
             if (functions.length() > 0) {
                 functions += ",";
@@ -222,6 +226,9 @@
                 split[i] = null;
             }
         }
+        if (split.length == 1 && split[0] == null) {
+            return "none";
+        }
         StringBuilder builder = new StringBuilder();
          for (int i = 0; i < split.length; i++) {
             String s = split[i];
@@ -365,11 +372,7 @@
             for (int i = 0; i < 20; i++) {
                 // State transition is done when sys.usb.state is set to the new configuration
                 if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
-                try {
-                    // try again in 50ms
-                    Thread.sleep(50);
-                } catch (InterruptedException e) {
-                }
+                SystemClock.sleep(50);
             }
             Slog.e(TAG, "waitForState(" + state + ") FAILED");
             return false;
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 3043da2..c29ef3f 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -21,10 +21,12 @@
 import com.android.server.wm.WindowManagerService.H;
 
 import android.content.pm.ActivityInfo;
+import android.graphics.Matrix;
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Slog;
 import android.view.IApplicationToken;
+import android.view.Surface;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
@@ -56,7 +58,8 @@
     // These are used for determining when all windows associated with
     // an activity have been drawn, so they can be made visible together
     // at the same time.
-    int lastTransactionSequence;
+    // initialize so that it doesn't match mTransactionSequence which is an int.
+    long lastTransactionSequence = Long.MIN_VALUE;
     int numInterestingWindows;
     int numDrawnWindows;
     boolean inPendingTransaction;
@@ -89,6 +92,7 @@
 
     boolean animating;
     Animation animation;
+    boolean animInitialized;
     boolean hasTransformation;
     final Transformation transformation = new Transformation();
 
@@ -104,6 +108,15 @@
     boolean startingMoved;
     boolean firstWindowDrawn;
 
+    // Special surface for thumbnail animation.
+    Surface thumbnail;
+    int thumbnailTransactionSeq;
+    int thumbnailX;
+    int thumbnailY;
+    int thumbnailLayer;
+    Animation thumbnailAnimation;
+    final Transformation thumbnailTransformation = new Transformation();
+
     // Input application handle used by the input dispatcher.
     final InputApplicationHandle mInputApplicationHandle;
 
@@ -113,14 +126,14 @@
         appWindowToken = this;
         appToken = _token;
         mInputApplicationHandle = new InputApplicationHandle(this);
-        lastTransactionSequence = service.mTransactionSequence-1;
     }
 
-    public void setAnimation(Animation anim) {
+    public void setAnimation(Animation anim, boolean initialized) {
         if (WindowManagerService.localLOGV) Slog.v(
             WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
         animation = anim;
         animating = false;
+        animInitialized = initialized;
         anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
         anim.scaleCurrentDuration(service.mTransitionAnimationScale);
         int zorder = anim.getZAdjustment();
@@ -146,6 +159,7 @@
             if (WindowManagerService.localLOGV) Slog.v(
                 WindowManagerService.TAG, "Setting dummy animation in " + this);
             animation = WindowManagerService.sDummyAnimation;
+            animInitialized = false;
         }
     }
 
@@ -153,15 +167,28 @@
         if (animation != null) {
             animation = null;
             animating = true;
+            animInitialized = false;
+        }
+        clearThumbnail();
+    }
+
+    public void clearThumbnail() {
+        if (thumbnail != null) {
+            thumbnail.destroy();
+            thumbnail = null;
         }
     }
 
     void updateLayers() {
         final int N = allAppWindows.size();
         final int adj = animLayerAdjustment;
+        thumbnailLayer = -1;
         for (int i=0; i<N; i++) {
             WindowState w = allAppWindows.get(i);
             w.mAnimLayer = w.mLayer + adj;
+            if (w.mAnimLayer > thumbnailLayer) {
+                thumbnailLayer = w.mAnimLayer;
+            }
             if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
                     + w.mAnimLayer);
             if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
@@ -203,6 +230,38 @@
         return isAnimating;
     }
 
+    private void stepThumbnailAnimation(long currentTime) {
+        thumbnailTransformation.clear();
+        thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
+        thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
+        final boolean screenAnimation = service.mAnimator.mScreenRotationAnimation != null
+                && service.mAnimator.mScreenRotationAnimation.isAnimating();
+        if (screenAnimation) {
+            thumbnailTransformation.postCompose(
+                    service.mAnimator.mScreenRotationAnimation.getEnterTransformation());
+        }
+        // cache often used attributes locally
+        final float tmpFloats[] = service.mTmpFloats;
+        thumbnailTransformation.getMatrix().getValues(tmpFloats);
+        if (WindowManagerService.SHOW_TRANSACTIONS) service.logSurface(thumbnail,
+                "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
+                + ", " + tmpFloats[Matrix.MTRANS_Y], null);
+        thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
+        if (WindowManagerService.SHOW_TRANSACTIONS) service.logSurface(thumbnail,
+                "thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
+                + " layer=" + thumbnailLayer
+                + " matrix=[" + tmpFloats[Matrix.MSCALE_X]
+                + "," + tmpFloats[Matrix.MSKEW_Y]
+                + "][" + tmpFloats[Matrix.MSKEW_X]
+                + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
+        thumbnail.setAlpha(thumbnailTransformation.getAlpha());
+        // The thumbnail is layered below the window immediately above this
+        // token's anim layer.
+        thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
+                - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+        thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
+                tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
+    }
 
     private boolean stepAnimation(long currentTime) {
         if (animation == null) {
@@ -215,6 +274,7 @@
             ": more=" + more + ", xform=" + transformation);
         if (!more) {
             animation = null;
+            clearThumbnail();
             if (WindowManagerService.DEBUG_ANIM) Slog.v(
                 WindowManagerService.TAG, "Finished animation in " + this +
                 " @ " + currentTime);
@@ -243,12 +303,22 @@
                         " @ " + currentTime + ": dw=" + dw + " dh=" + dh
                         + " scale=" + service.mTransitionAnimationScale
                         + " allDrawn=" + allDrawn + " animating=" + animating);
-                    animation.initialize(dw, dh, dw, dh);
+                    if (!animInitialized) {
+                        animation.initialize(dw, dh, dw, dh);
+                    }
                     animation.setStartTime(currentTime);
                     animating = true;
+                    if (thumbnail != null) {
+                        thumbnail.show();
+                        thumbnailAnimation.setStartTime(currentTime);
+                    }
                 }
                 if (stepAnimation(currentTime)) {
-                    // we're done!
+                    // animation isn't over, step any thumbnail and that's
+                    // it for now.
+                    if (thumbnail != null) {
+                        stepThumbnailAnimation(currentTime);
+                    }
                     return true;
                 }
             }
@@ -440,6 +510,15 @@
                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
                     pw.print(" startingMoved"); pw.println(startingMoved);
         }
+        if (thumbnail != null) {
+            pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
+                    pw.print(" x="); pw.print(thumbnailX);
+                    pw.print(" y="); pw.print(thumbnailY);
+                    pw.print(" layer="); pw.println(thumbnailLayer);
+            pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation);
+            pw.print(prefix); pw.print("thumbnailTransformation=");
+                    pw.println(thumbnailTransformation.toShortString());
+        }
     }
 
     @Override
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
new file mode 100644
index 0000000..7aa6716
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -0,0 +1,601 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Slog;
+import android.view.Surface;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerPolicy;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+
+import com.android.internal.policy.impl.PhoneWindowManager;
+
+/**
+ * @author cmautner@google.com (Craig Mautner)
+ * Singleton class that carries out the animations and Surface operations in a separate task
+ * on behalf of WindowManagerService.
+ */
+public class WindowAnimator {
+    private static final String TAG = "WindowAnimator";
+
+    final WindowManagerService mService;
+    final Context mContext;
+    final WindowManagerPolicy mPolicy;
+
+    boolean mAnimating;
+    boolean mUpdateRotation;
+    boolean mTokenMayBeDrawn;
+    boolean mForceHiding;
+    WindowState mWindowAnimationBackground;
+    int mWindowAnimationBackgroundColor;
+    int mAdjResult;
+
+    int mPendingLayoutChanges;
+
+    /** Overall window dimensions */
+    int mDw, mDh;
+
+    /** Interior window dimensions */
+    int mInnerDw, mInnerDh;
+
+    /** Time of current animation step. Reset on each iteration */
+    long mCurrentTime;
+
+    /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
+     * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
+    private int mTransactionSequence;
+
+    /** The one and only screen rotation if one is happening */
+    ScreenRotationAnimation mScreenRotationAnimation = null;
+
+    WindowAnimator(final WindowManagerService service, final Context context,
+            final WindowManagerPolicy policy) {
+        mService = service;
+        mContext = context;
+        mPolicy = policy;
+    }
+
+    private void updateWindowsAppsAndRotationAnimationsLocked() {
+        int i;
+        final int NAT = mService.mAppTokens.size();
+        for (i=0; i<NAT; i++) {
+            final AppWindowToken appToken = mService.mAppTokens.get(i);
+            final boolean wasAnimating = appToken.animation != null;
+            if (appToken.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
+                mAnimating = true;
+            } else if (wasAnimating) {
+                // stopped animating, do one more pass through the layout
+                mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+            }
+        }
+        
+        final int NEAT = mService.mExitingAppTokens.size();
+        for (i=0; i<NEAT; i++) {
+            final AppWindowToken appToken = mService.mExitingAppTokens.get(i);
+            final boolean wasAnimating = appToken.animation != null;
+            if (appToken.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
+                mAnimating = true;
+            } else if (wasAnimating) {
+                // stopped animating, do one more pass through the layout
+                mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+            }
+        }
+
+        if (mScreenRotationAnimation != null &&
+                (mScreenRotationAnimation.isAnimating() ||
+                        mScreenRotationAnimation.mFinishAnimReady)) {
+            if (mScreenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
+                mUpdateRotation = false;
+                mAnimating = true;
+            } else {
+                mUpdateRotation = true;
+                mScreenRotationAnimation.kill();
+                mScreenRotationAnimation = null;
+            }
+        }
+    }
+
+    private void updateWindowsAndWallpaperLocked() {
+        ++mTransactionSequence;
+
+        for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
+            WindowState w = mService.mWindows.get(i);
+
+            final WindowManager.LayoutParams attrs = w.mAttrs;
+
+            if (w.mSurface != null) {
+                // Take care of the window being ready to display.
+                if (w.commitFinishDrawingLocked(mCurrentTime)) {
+                    if ((w.mAttrs.flags
+                            & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+                        if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
+                                "First draw done in potential wallpaper target " + w);
+                        mService.mInnerFields.mWallpaperMayChange = true;
+                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                    }
+                }
+
+                // If the window has moved due to its containing
+                // content frame changing, then we'd like to animate
+                // it.  The checks here are ordered by what is least
+                // likely to be true first.
+                if (w.shouldAnimateMove()) {
+                    // Frame has moved, containing content frame
+                    // has also moved, and we're not currently animating...
+                    // let's do something.
+                    Animation a = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.window_move_from_decor);
+                    w.setAnimation(a);
+                    w.mAnimDw = w.mLastFrame.left - w.mFrame.left;
+                    w.mAnimDh = w.mLastFrame.top - w.mFrame.top;
+                } else {
+                    w.mAnimDw = mInnerDw;
+                    w.mAnimDh = mInnerDh;
+                }
+
+                final boolean wasAnimating = w.mWasAnimating;
+                final boolean nowAnimating = w.stepAnimationLocked(mCurrentTime);
+
+                if (WindowManagerService.DEBUG_WALLPAPER) {
+                    Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
+                            ", nowAnimating=" + nowAnimating);
+                }
+
+                // If this window is animating, make a note that we have
+                // an animating window and take care of a request to run
+                // a detached wallpaper animation.
+                if (nowAnimating) {
+                    if (w.mAnimation != null) {
+                        if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
+                                && w.mAnimation.getDetachWallpaper()) {
+                            mService.mInnerFields.mDetachedWallpaper = w;
+                        }
+                        if (w.mAnimation.getBackgroundColor() != 0) {
+                            if (mWindowAnimationBackground == null
+                                    || (w.mAnimLayer < mWindowAnimationBackground.mAnimLayer)) {
+                                mWindowAnimationBackground = w;
+                                mWindowAnimationBackgroundColor =
+                                        w.mAnimation.getBackgroundColor();
+                            }
+                        }
+                    }
+                    mAnimating = true;
+                }
+
+                // If this window's app token is running a detached wallpaper
+                // animation, make a note so we can ensure the wallpaper is
+                // displayed behind it.
+                if (w.mAppToken != null && w.mAppToken.animation != null
+                        && w.mAppToken.animating) {
+                    if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
+                            && w.mAppToken.animation.getDetachWallpaper()) {
+                        mService.mInnerFields.mDetachedWallpaper = w;
+                    }
+                    if (w.mAppToken.animation.getBackgroundColor() != 0) {
+                        if (mWindowAnimationBackground == null
+                                || (w.mAnimLayer <
+                                        mWindowAnimationBackground.mAnimLayer)) {
+                            mWindowAnimationBackground = w;
+                            mWindowAnimationBackgroundColor =
+                                    w.mAppToken.animation.getBackgroundColor();
+                        }
+                    }
+                }
+
+                if (wasAnimating && !w.mAnimating && mService.mWallpaperTarget == w) {
+                    mService.mInnerFields.mWallpaperMayChange = true;
+                    mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                }
+
+                if (mPolicy.doesForceHide(w, attrs)) {
+                    if (!wasAnimating && nowAnimating) {
+                        if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                                "Animation started that could impact force hide: "
+                                + w);
+                        mService.mInnerFields.mWallpaperForceHidingChanged = true;
+                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                        mService.mFocusMayChange = true;
+                    } else if (w.isReadyForDisplay() && w.mAnimation == null) {
+                        mForceHiding = true;
+                    }
+                } else if (mPolicy.canBeForceHidden(w, attrs)) {
+                    boolean changed;
+                    if (mForceHiding) {
+                        changed = w.hideLw(false, false);
+                        if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
+                                "Now policy hidden: " + w);
+                    } else {
+                        changed = w.showLw(false, false);
+                        if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
+                                "Now policy shown: " + w);
+                        if (changed) {
+                            if (mService.mInnerFields.mWallpaperForceHidingChanged
+                                    && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
+                                // Assume we will need to animate.  If
+                                // we don't (because the wallpaper will
+                                // stay with the lock screen), then we will
+                                // clean up later.
+                                Animation a = mPolicy.createForceHideEnterAnimation();
+                                if (a != null) {
+                                    w.setAnimation(a);
+                                }
+                            }
+                            if (mCurrentFocus == null || mCurrentFocus.mLayer < w.mLayer) {
+                                // We are showing on to of the current
+                                // focus, so re-evaluate focus to make
+                                // sure it is correct.
+                                mService.mFocusMayChange = true;
+                            }
+                        }
+                    }
+                    if (changed && (attrs.flags
+                            & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+                        mService.mInnerFields.mWallpaperMayChange = true;
+                        mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+                    }
+                }
+            }
+
+            final AppWindowToken atoken = w.mAppToken;
+            if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
+                if (atoken.lastTransactionSequence != mTransactionSequence) {
+                    atoken.lastTransactionSequence = mTransactionSequence;
+                    atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
+                    atoken.startingDisplayed = false;
+                }
+                if ((w.isOnScreen() || w.mAttrs.type
+                        == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
+                        && !w.mExiting && !w.mDestroying) {
+                    if (WindowManagerService.DEBUG_VISIBILITY ||
+                            WindowManagerService.DEBUG_ORIENTATION) {
+                        Slog.v(TAG, "Eval win " + w + ": isDrawn="
+                                + w.isDrawnLw()
+                                + ", isAnimating=" + w.isAnimating());
+                        if (!w.isDrawnLw()) {
+                            Slog.v(TAG, "Not displayed: s=" + w.mSurface
+                                    + " pv=" + w.mPolicyVisibility
+                                    + " dp=" + w.mDrawPending
+                                    + " cdp=" + w.mCommitDrawPending
+                                    + " ah=" + w.mAttachedHidden
+                                    + " th=" + atoken.hiddenRequested
+                                    + " a=" + w.mAnimating);
+                        }
+                    }
+                    if (w != atoken.startingWindow) {
+                        if (!atoken.freezingScreen || !w.mAppFreezing) {
+                            atoken.numInterestingWindows++;
+                            if (w.isDrawnLw()) {
+                                atoken.numDrawnWindows++;
+                                if (WindowManagerService.DEBUG_VISIBILITY ||
+                                        WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+                                        "tokenMayBeDrawn: " + atoken
+                                        + " freezingScreen=" + atoken.freezingScreen
+                                        + " mAppFreezing=" + w.mAppFreezing);
+                                mTokenMayBeDrawn = true;
+                            }
+                        }
+                    } else if (w.isDrawnLw()) {
+                        atoken.startingDisplayed = true;
+                    }
+                }
+            } else if (w.mReadyToShow) {
+                w.performShowLocked();
+                mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+            }
+            if (atoken != null && atoken.thumbnail != null) {
+                if (atoken.thumbnailTransactionSeq != mTransactionSequence) {
+                    atoken.thumbnailTransactionSeq = mTransactionSequence;
+                    atoken.thumbnailLayer = 0;
+                }
+                if (atoken.thumbnailLayer < w.mAnimLayer) {
+                    atoken.thumbnailLayer = w.mAnimLayer;
+                }
+            }
+        } // end forall windows
+    }
+
+    private void testTokenMayBeDrawnLocked() {
+        // See if any windows have been drawn, so they (and others
+        // associated with them) can now be shown.
+        final int NT = mService.mAppTokens.size();
+        for (int i=0; i<NT; i++) {
+            AppWindowToken wtoken = mService.mAppTokens.get(i);
+            if (wtoken.freezingScreen) {
+                int numInteresting = wtoken.numInterestingWindows;
+                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
+                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                            "allDrawn: " + wtoken
+                            + " interesting=" + numInteresting
+                            + " drawn=" + wtoken.numDrawnWindows);
+                    wtoken.showAllWindowsLocked();
+                    mService.unsetAppFreezingScreenLocked(wtoken, false, true);
+                    if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
+                            "Setting mOrientationChangeComplete=true because wtoken "
+                            + wtoken + " numInteresting=" + numInteresting
+                            + " numDrawn=" + wtoken.numDrawnWindows);
+                    mService.mInnerFields.mOrientationChangeComplete = true;
+                }
+            } else if (!wtoken.allDrawn) {
+                int numInteresting = wtoken.numInterestingWindows;
+                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
+                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                            "allDrawn: " + wtoken
+                            + " interesting=" + numInteresting
+                            + " drawn=" + wtoken.numDrawnWindows);
+                    wtoken.allDrawn = true;
+                    mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
+
+                    // We can now show all of the drawn windows!
+                    if (!mService.mOpeningApps.contains(wtoken)) {
+                        mAnimating |= wtoken.showAllWindowsLocked();
+                    }
+                }
+            }
+        }
+    }
+
+    private void performAnimationsLocked() {
+        if (WindowManagerService.DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
+                + mTransactionSequence + " mAnimating="
+                + mAnimating);
+
+        mTokenMayBeDrawn = false;
+        mService.mInnerFields.mWallpaperMayChange = false;
+        mForceHiding = false;
+        mService.mInnerFields.mDetachedWallpaper = null;
+        mWindowAnimationBackground = null;
+        mWindowAnimationBackgroundColor = 0;
+
+        updateWindowsAndWallpaperLocked();
+
+        if (mTokenMayBeDrawn) {
+            testTokenMayBeDrawnLocked();
+        }
+
+        if (WindowManagerService.DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
+                + Integer.toHexString(mPendingLayoutChanges));
+    }
+
+    public void prepareSurfaceLocked(final WindowState w, final boolean recoveringMemory) {
+        if (w.mSurface == null) {
+            if (w.mOrientationChanging) {
+                if (WindowManagerService.DEBUG_ORIENTATION) {
+                    Slog.v(TAG, "Orientation change skips hidden " + w);
+                }
+                w.mOrientationChanging = false;
+            }
+            return;
+        }
+
+        boolean displayed = false;
+
+        w.computeShownFrameLocked();
+
+        int width, height;
+        if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
+            // for a scaled surface, we just want to use
+            // the requested size.
+            width  = w.mRequestedWidth;
+            height = w.mRequestedHeight;
+        } else {
+            width = w.mCompatFrame.width();
+            height = w.mCompatFrame.height();
+        }
+
+        if (width < 1) {
+            width = 1;
+        }
+        if (height < 1) {
+            height = 1;
+        }
+        final boolean surfaceResized = w.mSurfaceW != width || w.mSurfaceH != height;
+        if (surfaceResized) {
+            w.mSurfaceW = width;
+            w.mSurfaceH = height;
+        }
+
+        if (w.mSurfaceX != w.mShownFrame.left
+                || w.mSurfaceY != w.mShownFrame.top) {
+            try {
+                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+                        "POS " + w.mShownFrame.left
+                        + ", " + w.mShownFrame.top, null);
+                w.mSurfaceX = w.mShownFrame.left;
+                w.mSurfaceY = w.mShownFrame.top;
+                w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
+            } catch (RuntimeException e) {
+                Slog.w(TAG, "Error positioning surface of " + w
+                        + " pos=(" + w.mShownFrame.left
+                        + "," + w.mShownFrame.top + ")", e);
+                if (!recoveringMemory) {
+                    mService.reclaimSomeSurfaceMemoryLocked(w, "position", true);
+                }
+            }
+        }
+
+        if (surfaceResized) {
+            try {
+                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+                        "SIZE " + width + "x" + height, null);
+                w.mSurfaceResized = true;
+                w.mSurface.setSize(width, height);
+            } catch (RuntimeException e) {
+                // If something goes wrong with the surface (such
+                // as running out of memory), don't take down the
+                // entire system.
+                Slog.e(TAG, "Error resizing surface of " + w
+                        + " size=(" + width + "x" + height + ")", e);
+                if (!recoveringMemory) {
+                    mService.reclaimSomeSurfaceMemoryLocked(w, "size", true);
+                }
+            }
+        }
+
+        if (w.mAttachedHidden || !w.isReadyForDisplay()) {
+            if (!w.mLastHidden) {
+                //dump();
+                w.mLastHidden = true;
+                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+                        "HIDE (performLayout)", null);
+                if (w.mSurface != null) {
+                    w.mSurfaceShown = false;
+                    try {
+                        w.mSurface.hide();
+                    } catch (RuntimeException e) {
+                        Slog.w(TAG, "Exception hiding surface in " + w);
+                    }
+                }
+            }
+            // If we are waiting for this window to handle an
+            // orientation change, well, it is hidden, so
+            // doesn't really matter.  Note that this does
+            // introduce a potential glitch if the window
+            // becomes unhidden before it has drawn for the
+            // new orientation.
+            if (w.mOrientationChanging) {
+                w.mOrientationChanging = false;
+                if (WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+                        "Orientation change skips hidden " + w);
+            }
+        } else if (w.mLastLayer != w.mAnimLayer
+                || w.mLastAlpha != w.mShownAlpha
+                || w.mLastDsDx != w.mDsDx
+                || w.mLastDtDx != w.mDtDx
+                || w.mLastDsDy != w.mDsDy
+                || w.mLastDtDy != w.mDtDy
+                || w.mLastHScale != w.mHScale
+                || w.mLastVScale != w.mVScale
+                || w.mLastHidden) {
+            displayed = true;
+            w.mLastAlpha = w.mShownAlpha;
+            w.mLastLayer = w.mAnimLayer;
+            w.mLastDsDx = w.mDsDx;
+            w.mLastDtDx = w.mDtDx;
+            w.mLastDsDy = w.mDsDy;
+            w.mLastDtDy = w.mDtDy;
+            w.mLastHScale = w.mHScale;
+            w.mLastVScale = w.mVScale;
+            if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+                    "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
+                    + " matrix=[" + (w.mDsDx*w.mHScale)
+                    + "," + (w.mDtDx*w.mVScale)
+                    + "][" + (w.mDsDy*w.mHScale)
+                    + "," + (w.mDtDy*w.mVScale) + "]", null);
+            if (w.mSurface != null) {
+                try {
+                    w.mSurfaceAlpha = w.mShownAlpha;
+                    w.mSurface.setAlpha(w.mShownAlpha);
+                    w.mSurfaceLayer = w.mAnimLayer;
+                    w.mSurface.setLayer(w.mAnimLayer);
+                    w.mSurface.setMatrix(
+                            w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
+                            w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
+                } catch (RuntimeException e) {
+                    Slog.w(TAG, "Error updating surface in " + w, e);
+                    if (!recoveringMemory) {
+                        mService.reclaimSomeSurfaceMemoryLocked(w, "update", true);
+                    }
+                }
+            }
+
+            if (w.mLastHidden && w.isDrawnLw()
+                    && !w.mReadyToShow) {
+                if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+                        "SHOW (performLayout)", null);
+                if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
+                        + " during relayout");
+                if (mService.showSurfaceRobustlyLocked(w)) {
+                    w.mHasDrawn = true;
+                    w.mLastHidden = false;
+                } else {
+                    w.mOrientationChanging = false;
+                }
+            }
+            if (w.mSurface != null) {
+                w.mToken.hasVisible = true;
+            }
+        } else {
+            displayed = true;
+        }
+
+        if (displayed) {
+            if (w.mOrientationChanging) {
+                if (!w.isDrawnLw()) {
+                    mService.mInnerFields.mOrientationChangeComplete = false;
+                    if (WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+                            "Orientation continue waiting for draw in " + w);
+                } else {
+                    w.mOrientationChanging = false;
+                    if (WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
+                            "Orientation change complete in " + w);
+                }
+            }
+            w.mToken.hasVisible = true;
+        }
+    }
+
+    void animate() {
+        mPendingLayoutChanges = 0;
+        mCurrentTime = SystemClock.uptimeMillis();
+
+        // Update animations of all applications, including those
+        // associated with exiting/removed apps
+        Surface.openTransaction();
+
+        try {
+            updateWindowsAppsAndRotationAnimationsLocked();
+            performAnimationsLocked();
+
+            // THIRD LOOP: Update the surfaces of all windows.
+
+            if (mScreenRotationAnimation != null) {
+                mScreenRotationAnimation.updateSurfaces();
+            }
+
+            final int N = mService.mWindows.size();
+            for (int i=N-1; i>=0; i--) {
+                WindowState w = mService.mWindows.get(i);
+                prepareSurfaceLocked(w, true);
+            }
+
+            if (mService.mDimAnimator != null && mService.mDimAnimator.mDimShown) {
+                mAnimating |= mService.mDimAnimator.updateSurface(mService.mInnerFields.mDimming,
+                            mCurrentTime, !mService.okToDisplay());
+            }
+
+            if (mService.mBlackFrame != null) {
+                if (mScreenRotationAnimation != null) {
+                    mService.mBlackFrame.setMatrix(
+                            mScreenRotationAnimation.getEnterTransformation().getMatrix());
+                } else {
+                    mService.mBlackFrame.clearMatrix();
+                }
+            }
+        } catch (RuntimeException e) {
+            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
+        } finally {
+            Surface.closeTransaction();
+        }
+    }
+
+    WindowState mCurrentFocus;
+    void setCurrentFocus(WindowState currentFocus) {
+        mCurrentFocus = currentFocus;
+    }
+
+    void setDisplayDimensions(final int curWidth, final int curHeight,
+                        final int appWidth, final int appHeight) {
+        mDw = curWidth;
+        mDh = curHeight;
+        mInnerDw = appWidth;
+        mInnerDh = appHeight;
+    }
+
+}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 31a2788..a978b35 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -117,8 +117,12 @@
 import android.view.WindowManagerPolicy;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManagerPolicy.FakeWindow;
+import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
 import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.view.animation.ScaleAnimation;
 import android.view.animation.Transformation;
 
 import java.io.BufferedWriter;
@@ -194,6 +198,18 @@
     static final int LAYER_OFFSET_DIM = 1;
 
     /**
+     * Blur surface layer is immediately below dim layer.
+     */
+    static final int LAYER_OFFSET_BLUR = 2;
+
+    /**
+     * Animation thumbnail is as far as possible below the window above
+     * the thumbnail (or in other words as far as possible above the window
+     * below it).
+     */
+    static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1;
+
+    /**
      * Layer at which to put the rotation freeze snapshot.
      */
     static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1;
@@ -408,15 +424,12 @@
     IInputMethodManager mInputMethodManager;
 
     SurfaceSession mFxSession;
-    private DimAnimator mDimAnimator = null;
+    DimAnimator mDimAnimator = null;
     Watermark mWatermark;
     StrictModeFlash mStrictModeFlash;
-    ScreenRotationAnimation mScreenRotationAnimation;
 
     BlackFrame mBlackFrame;
 
-    int mTransactionSequence = 0;
-
     final float[] mTmpFloats = new float[9];
 
     boolean mSafeMode;
@@ -482,8 +495,12 @@
     // made visible or hidden at the next transition.
     int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
     String mNextAppTransitionPackage;
+    Bitmap mNextAppTransitionThumbnail;
+    IRemoteCallback mNextAppTransitionCallback;
     int mNextAppTransitionEnter;
     int mNextAppTransitionExit;
+    int mNextAppTransitionStartX;
+    int mNextAppTransitionStartY;
     boolean mAppTransitionReady = false;
     boolean mAppTransitionRunning = false;
     boolean mAppTransitionTimeout = false;
@@ -575,26 +592,24 @@
 
     /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
      * methods. */
-    private class LayoutAndSurfaceFields {
-        private boolean mAnimating = false;
-        private boolean mWallpaperForceHidingChanged = false;
-        private boolean mTokenMayBeDrawn = false;
-        private boolean mWallpaperMayChange = false;
-        private boolean mForceHiding = false;
-        private WindowState mDetachedWallpaper = null;
-        private WindowState mWindowAnimationBackground = null;
-        private int mWindowAnimationBackgroundColor = 0;
-        private boolean mOrientationChangeComplete = true;
+    class LayoutAndSurfaceFields {
+        boolean mWallpaperForceHidingChanged = false;
+        boolean mWallpaperMayChange = false;
+        WindowState mDetachedWallpaper = null;
+        boolean mOrientationChangeComplete = true;
         private int mAdjResult = 0;
         private Session mHoldScreen = null;
         private boolean mObscured = false;
-        private boolean mDimming = false;
+        boolean mDimming = false;
         private boolean mSyswin = false;
         private float mScreenBrightness = -1;
         private float mButtonBrightness = -1;
         private boolean mUpdateRotation = false;
     }
-    private LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields();
+    LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields();
+
+    /** Only do a maximum of 6 repeated layouts. After that quit */
+    private int mLayoutRepeatCount;
 
     private final class AnimationRunnable implements Runnable {
         @Override
@@ -607,6 +622,8 @@
     }
     final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
     boolean mAnimationScheduled;
+    
+    final WindowAnimator mAnimator;
 
     final class DragInputEventReceiver extends InputEventReceiver {
         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
@@ -828,6 +845,7 @@
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
         mInputManager = new InputManager(context, this);
+        mAnimator = new WindowAnimator(this, context, mPolicy);
 
         PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
         thr.start();
@@ -1902,7 +1920,7 @@
             rawChanged = true;
         }
 
-        if (rawChanged && (wallpaperWin.getAttrs().privateFlags &
+        if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
                     WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
             try {
                 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
@@ -2209,7 +2227,7 @@
             if (mInTouchMode) {
                 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
             }
-            if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
+            if (win.mAppToken == null || !win.mAppToken.clientHidden) {
                 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
             }
 
@@ -2276,7 +2294,7 @@
             + ", surface=" + win.mSurface);
 
         final long origId = Binder.clearCallingIdentity();
-        
+
         win.disposeInputChannel();
 
         if (DEBUG_APP_TRANSITIONS) Slog.v(
@@ -2297,10 +2315,11 @@
         if (win.mSurface != null && okToDisplay()) {
             // If we are not currently running the exit animation, we
             // need to see about starting one.
-            if (wasVisible=win.isWinVisibleLw()) {
+            wasVisible = win.isWinVisibleLw();
+            if (wasVisible) {
 
                 int transit = WindowManagerPolicy.TRANSIT_EXIT;
-                if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
+                if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
                     transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
                 }
                 // Try starting an animation.
@@ -2445,6 +2464,15 @@
             Slog.i(TAG, str);
         }
     }
+
+    static void logSurface(Surface s, String title, String msg, RuntimeException where) {
+        String str = "  SURFACE " + s + ": " + msg + " / " + title;
+        if (where != null) {
+            Slog.i(TAG, str, where);
+        } else {
+            Slog.i(TAG, str);
+        }
+    }
     
     void setTransparentRegionWindow(Session session, IWindow client, Region region) {
         long origId = Binder.clearCallingIdentity();
@@ -2765,7 +2793,7 @@
                         // Try starting an animation; if there isn't one, we
                         // can destroy the surface right away.
                         int transit = WindowManagerPolicy.TRANSIT_EXIT;
-                        if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
+                        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
                             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
                         }
                         if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
@@ -3085,6 +3113,63 @@
         return null;
     }
 
+    private Animation createThumbnailAnimationLocked(int transit,
+            boolean enter, boolean thumb) {
+        Animation a;
+        final float thumbWidth = mNextAppTransitionThumbnail.getWidth();
+        final float thumbHeight = mNextAppTransitionThumbnail.getHeight();
+        // Pick the desired duration.  If this is an inter-activity transition,
+        // it  is the standard duration for that.  Otherwise we use the longer
+        // task transition duration.
+        int duration;
+        switch (transit) {
+            case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
+            case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
+                duration = mContext.getResources().getInteger(
+                        com.android.internal.R.integer.config_shortAnimTime);
+                break;
+            default:
+                duration = 500;
+                break;
+            
+        }
+        if (thumb) {
+            // Animation for zooming thumbnail from its initial size to
+            // filling the screen.
+            Animation scale = new ScaleAnimation(
+                    1, mAppDisplayWidth/thumbWidth,
+                    1, mAppDisplayHeight/thumbHeight,
+                    mNextAppTransitionStartX + thumbWidth/2,
+                    mNextAppTransitionStartY + thumbHeight/2);
+            AnimationSet set = new AnimationSet(true);
+            Animation alpha = new AlphaAnimation(1, 0);
+            scale.setDuration(duration);
+            set.addAnimation(scale);
+            alpha.setDuration(duration);
+            set.addAnimation(alpha);
+            a = set;
+        } else if (enter) {
+            // Entering app zooms out from the center of the thumbnail.
+            a = new ScaleAnimation(
+                    thumbWidth/mAppDisplayWidth, 1,
+                    thumbHeight/mAppDisplayHeight, 1,
+                    mNextAppTransitionStartX + thumbWidth/2,
+                    mNextAppTransitionStartY + thumbHeight/2);
+            a.setDuration(duration);
+        } else {
+            // Exiting app just holds in place.
+            a = new AlphaAnimation(1, 1);
+            a.setDuration(duration);
+        }
+        a.setFillAfter(true);
+        final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
+                com.android.internal.R.interpolator.decelerate_quint);
+        a.setInterpolator(interpolator);
+        a.initialize(mAppDisplayWidth, mAppDisplayHeight,
+                mAppDisplayWidth, mAppDisplayHeight);
+        return a;
+    }
+
     private boolean applyAnimationLocked(AppWindowToken wtoken,
             WindowManager.LayoutParams lp, int transit, boolean enter) {
         // Only apply an animation if the display isn't frozen.  If it is
@@ -3093,7 +3178,11 @@
         // is running.
         if (okToDisplay()) {
             Animation a;
-            if (mNextAppTransitionPackage != null) {
+            boolean initialized = false;
+            if (mNextAppTransitionThumbnail != null) {
+                a = createThumbnailAnimationLocked(transit, enter, false);
+                initialized = true;
+            } else if (mNextAppTransitionPackage != null) {
                 a = loadAnimation(mNextAppTransitionPackage, enter ?
                         mNextAppTransitionEnter : mNextAppTransitionExit);
             } else {
@@ -3165,7 +3254,7 @@
                     }
                     Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
                 }
-                wtoken.setAnimation(a);
+                wtoken.setAnimation(a, initialized);
             }
         } else {
             wtoken.clearAnimation();
@@ -3693,11 +3782,23 @@
             int enterAnim, int exitAnim) {
         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
             mNextAppTransitionPackage = packageName;
+            mNextAppTransitionThumbnail = null;
             mNextAppTransitionEnter = enterAnim;
             mNextAppTransitionExit = exitAnim;
         }
     }
 
+    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
+            int startY, IRemoteCallback startedCallback) {
+        if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+            mNextAppTransitionPackage = null;
+            mNextAppTransitionThumbnail = srcThumb;
+            mNextAppTransitionStartX = startX;
+            mNextAppTransitionStartY = startY;
+            mNextAppTransitionCallback = startedCallback;
+        }
+    }
+
     public void executeAppTransition() {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "executeAppTransition()")) {
@@ -3841,6 +3942,19 @@
                         mH.sendMessageAtFrontOfQueue(m);
                         return;
                     }
+                    if (ttoken.thumbnail != null) {
+                        // The old token is animating with a thumbnail, transfer
+                        // that to the new token.
+                        if (wtoken.thumbnail != null) {
+                            wtoken.thumbnail.destroy();
+                        }
+                        wtoken.thumbnail = ttoken.thumbnail;
+                        wtoken.thumbnailX = ttoken.thumbnailX;
+                        wtoken.thumbnailY = ttoken.thumbnailY;
+                        wtoken.thumbnailLayer = ttoken.thumbnailLayer;
+                        wtoken.thumbnailAnimation = ttoken.thumbnailAnimation;
+                        ttoken.thumbnail = null;
+                    }
                 }
             }
 
@@ -4236,6 +4350,7 @@
                     // Make sure there is no animation running on this token,
                     // so any windows associated with it will be removed as
                     // soon as their animations are complete
+                    wtoken.clearAnimation();
                     wtoken.animation = null;
                     wtoken.animating = false;
                 }
@@ -5382,7 +5497,8 @@
             return false;
         }
 
-        if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) {
+        if (mAnimator.mScreenRotationAnimation != null &&
+                mAnimator.mScreenRotationAnimation.isAnimating()) {
             // Rotation updates cannot be performed while the previous rotation change
             // animation is still in progress.  Skip this update.  We will try updating
             // again after the animation is finished and the display is unfrozen.
@@ -5452,9 +5568,9 @@
         try {
             // NOTE: We disable the rotation in the emulator because
             //       it doesn't support hardware OpenGL emulation yet.
-            if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
-                    && mScreenRotationAnimation.hasScreenshot()) {
-                if (mScreenRotationAnimation.setRotation(rotation, mFxSession,
+            if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
+                    && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
+                if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession,
                         MAX_ANIMATION_DURATION, mTransitionAnimationScale,
                         mCurDisplayWidth, mCurDisplayHeight)) {
                     scheduleAnimationLocked();
@@ -6156,6 +6272,8 @@
         synchronized(mDisplaySizeLock) {
             mAppDisplayWidth = appWidth;
             mAppDisplayHeight = appHeight;
+            mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight,
+                    mAppDisplayWidth, mAppDisplayHeight);
         }
         if (false) {
             Slog.i(TAG, "Set app display size: " + mAppDisplayWidth
@@ -6542,6 +6660,8 @@
                 }
                 mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
                 mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
+                mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight,
+                        mAppDisplayWidth, mAppDisplayHeight);
             }
             mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
                     mDisplay.getRawWidth(), mDisplay.getRawHeight(),
@@ -7458,10 +7578,25 @@
 
             } else {
                 mInLayout = false;
-                if (mLayoutNeeded) {
-                    requestTraversalLocked();
-                }
             }
+
+            if (mLayoutNeeded) {
+                if (++mLayoutRepeatCount < 6) {
+                    requestTraversalLocked();
+                } else {
+                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
+                    mLayoutRepeatCount = 0;
+                }
+            } else {
+                mLayoutRepeatCount = 0;
+            }
+            
+            if (mAnimator.mAnimating) {
+                // Do this even if requestTraversalLocked was called above so we get a frame drawn
+                // at the proper time as well as the one drawn early.
+                scheduleAnimationLocked();
+            }
+
             if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
                 mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
                 mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE));
@@ -7622,342 +7757,6 @@
 
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     * Update animations of all applications, including those associated with exiting/removed apps.
-     *
-     * @param currentTime The time which animations use for calculating transitions.
-     * @param innerDw Width of app window.
-     * @param innerDh Height of app window.
-     */
-    private void updateWindowsAppsAndRotationAnimationsLocked(long currentTime,
-                                                          int innerDw, int innerDh) {
-        int i;
-        final int NAT = mAppTokens.size();
-        for (i=0; i<NAT; i++) {
-            final AppWindowToken appToken = mAppTokens.get(i);
-            if (appToken.stepAnimationLocked(currentTime, innerDw, innerDh)) {
-                mInnerFields.mAnimating = true;
-            }
-        }
-        final int NEAT = mExitingAppTokens.size();
-        for (i=0; i<NEAT; i++) {
-            final AppWindowToken appToken = mExitingAppTokens.get(i);
-            if (appToken.stepAnimationLocked(currentTime, innerDw, innerDh)) {
-                mInnerFields.mAnimating = true;
-            }
-        }
-
-        if (mScreenRotationAnimation != null &&
-                (mScreenRotationAnimation.isAnimating() ||
-                        mScreenRotationAnimation.mFinishAnimReady)) {
-            if (mScreenRotationAnimation.stepAnimationLocked(currentTime)) {
-                mInnerFields.mUpdateRotation = false;
-                mInnerFields.mAnimating = true;
-            } else {
-                mInnerFields.mUpdateRotation = true;
-                mScreenRotationAnimation.kill();
-                mScreenRotationAnimation = null;
-            }
-        }
-    }
-
-    private void animateAndUpdateSurfaces(final long currentTime, final int dw, final int dh,
-                                          final int innerDw, final int innerDh, 
-                                          final boolean recoveringMemory) {
-        // Update animations of all applications, including those
-        // associated with exiting/removed apps
-        Surface.openTransaction();
-
-        try {
-            updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
-            mPendingLayoutChanges = performAnimationsLocked(currentTime, dw, dh,
-                    innerDw, innerDh);
-        
-            // THIRD LOOP: Update the surfaces of all windows.
-            
-            if (mScreenRotationAnimation != null) {
-                mScreenRotationAnimation.updateSurfaces();
-            }
-        
-            final int N = mWindows.size();
-            for (int i=N-1; i>=0; i--) {
-                WindowState w = mWindows.get(i);
-                prepareSurfaceLocked(w, recoveringMemory);
-            }
-        
-            if (mDimAnimator != null && mDimAnimator.mDimShown) {
-                mInnerFields.mAnimating |=
-                        mDimAnimator.updateSurface(mInnerFields.mDimming, currentTime,
-                            !okToDisplay());
-            }
-        
-            if (mBlackFrame != null) {
-                if (mScreenRotationAnimation != null) {
-                    mBlackFrame.setMatrix(
-                            mScreenRotationAnimation.getEnterTransformation().getMatrix());
-                } else {
-                    mBlackFrame.clearMatrix();
-                }
-            }
-        } catch (RuntimeException e) {
-            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
-        } finally {
-            Surface.closeTransaction();
-        }
-    }
-    
-    /**
-     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     *
-     * @param currentTime The time which animations use for calculating transitions.
-     * @param dw Width of app window.
-     * @param dh Height of app window.
-     * @param innerDw Width of app window.
-     * @param innerDh Height of app window.
-     */
-    private int updateWindowsAndWallpaperLocked(final long currentTime, final int dw, final int dh,
-                                                final int innerDw, final int innerDh) {
-        ++mTransactionSequence;
-
-        int changes = 0;
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            WindowState w = mWindows.get(i);
-
-            final WindowManager.LayoutParams attrs = w.mAttrs;
-
-            if (w.mSurface != null) {
-                // Take care of the window being ready to display.
-                if (w.commitFinishDrawingLocked(currentTime)) {
-                    if ((w.mAttrs.flags
-                            & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
-                        if (DEBUG_WALLPAPER) Slog.v(TAG,
-                                "First draw done in potential wallpaper target " + w);
-                        mInnerFields.mWallpaperMayChange = true;
-                        changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-                    }
-                }
-
-                // If the window has moved due to its containing
-                // content frame changing, then we'd like to animate
-                // it.  The checks here are ordered by what is least
-                // likely to be true first.
-                if (w.shouldAnimateMove()) {
-                    // Frame has moved, containing content frame
-                    // has also moved, and we're not currently animating...
-                    // let's do something.
-                    Animation a = AnimationUtils.loadAnimation(mContext,
-                            com.android.internal.R.anim.window_move_from_decor);
-                    w.setAnimation(a);
-                    w.mAnimDw = w.mLastFrame.left - w.mFrame.left;
-                    w.mAnimDh = w.mLastFrame.top - w.mFrame.top;
-                } else {
-                    w.mAnimDw = innerDw;
-                    w.mAnimDh = innerDh;
-                }
-
-                final boolean wasAnimating = w.mWasAnimating;
-                final boolean nowAnimating = w.stepAnimationLocked(currentTime);
-
-                if (DEBUG_WALLPAPER) {
-                    Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
-                            ", nowAnimating=" + nowAnimating);
-                }
-
-                // If this window is animating, make a note that we have
-                // an animating window and take care of a request to run
-                // a detached wallpaper animation.
-                if (nowAnimating) {
-                    if (w.mAnimation != null) {
-                        if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
-                                && w.mAnimation.getDetachWallpaper()) {
-                            mInnerFields.mDetachedWallpaper = w;
-                        }
-                        if (w.mAnimation.getBackgroundColor() != 0) {
-                            if (mInnerFields.mWindowAnimationBackground == null
-                                    || (w.mAnimLayer <
-                                            mInnerFields.mWindowAnimationBackground.mAnimLayer)) {
-                                mInnerFields.mWindowAnimationBackground = w;
-                                mInnerFields.mWindowAnimationBackgroundColor =
-                                        w.mAnimation.getBackgroundColor();
-                            }
-                        }
-                    }
-                    mInnerFields.mAnimating = true;
-                }
-
-                // If this window's app token is running a detached wallpaper
-                // animation, make a note so we can ensure the wallpaper is
-                // displayed behind it.
-                if (w.mAppToken != null && w.mAppToken.animation != null
-                        && w.mAppToken.animating) {
-                    if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
-                            && w.mAppToken.animation.getDetachWallpaper()) {
-                        mInnerFields.mDetachedWallpaper = w;
-                    }
-                    if (w.mAppToken.animation.getBackgroundColor() != 0) {
-                        if (mInnerFields.mWindowAnimationBackground == null
-                                || (w.mAnimLayer <
-                                        mInnerFields.mWindowAnimationBackground.mAnimLayer)) {
-                            mInnerFields.mWindowAnimationBackground = w;
-                            mInnerFields.mWindowAnimationBackgroundColor =
-                                    w.mAppToken.animation.getBackgroundColor();
-                        }
-                    }
-                }
-
-                if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
-                    mInnerFields.mWallpaperMayChange = true;
-                    changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-                }
-
-                if (mPolicy.doesForceHide(w, attrs)) {
-                    if (!wasAnimating && nowAnimating) {
-                        if (DEBUG_VISIBILITY) Slog.v(TAG,
-                                "Animation started that could impact force hide: "
-                                + w);
-                        mInnerFields.mWallpaperForceHidingChanged = true;
-                        changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-                        mFocusMayChange = true;
-                    } else if (w.isReadyForDisplay() && w.mAnimation == null) {
-                        mInnerFields.mForceHiding = true;
-                    }
-                } else if (mPolicy.canBeForceHidden(w, attrs)) {
-                    boolean changed;
-                    if (mInnerFields.mForceHiding) {
-                        changed = w.hideLw(false, false);
-                        if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
-                                "Now policy hidden: " + w);
-                    } else {
-                        changed = w.showLw(false, false);
-                        if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
-                                "Now policy shown: " + w);
-                        if (changed) {
-                            if (mInnerFields.mWallpaperForceHidingChanged
-                                    && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
-                                // Assume we will need to animate.  If
-                                // we don't (because the wallpaper will
-                                // stay with the lock screen), then we will
-                                // clean up later.
-                                Animation a = mPolicy.createForceHideEnterAnimation();
-                                if (a != null) {
-                                    w.setAnimation(a);
-                                }
-                            }
-                            if (mCurrentFocus == null ||
-                                    mCurrentFocus.mLayer < w.mLayer) {
-                                // We are showing on to of the current
-                                // focus, so re-evaluate focus to make
-                                // sure it is correct.
-                                mFocusMayChange = true;
-                            }
-                        }
-                    }
-                    if (changed && (attrs.flags
-                            & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
-                        mInnerFields.mWallpaperMayChange = true;
-                        changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-                    }
-                }
-            }
-
-            final AppWindowToken atoken = w.mAppToken;
-            if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
-                if (atoken.lastTransactionSequence != mTransactionSequence) {
-                    atoken.lastTransactionSequence = mTransactionSequence;
-                    atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
-                    atoken.startingDisplayed = false;
-                }
-                if ((w.isOnScreen() || w.mAttrs.type
-                        == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
-                        && !w.mExiting && !w.mDestroying) {
-                    if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
-                        Slog.v(TAG, "Eval win " + w + ": isDrawn="
-                                + w.isDrawnLw()
-                                + ", isAnimating=" + w.isAnimating());
-                        if (!w.isDrawnLw()) {
-                            Slog.v(TAG, "Not displayed: s=" + w.mSurface
-                                    + " pv=" + w.mPolicyVisibility
-                                    + " dp=" + w.mDrawPending
-                                    + " cdp=" + w.mCommitDrawPending
-                                    + " ah=" + w.mAttachedHidden
-                                    + " th=" + atoken.hiddenRequested
-                                    + " a=" + w.mAnimating);
-                        }
-                    }
-                    if (w != atoken.startingWindow) {
-                        if (!atoken.freezingScreen || !w.mAppFreezing) {
-                            atoken.numInterestingWindows++;
-                            if (w.isDrawnLw()) {
-                                atoken.numDrawnWindows++;
-                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
-                                        "tokenMayBeDrawn: " + atoken
-                                        + " freezingScreen=" + atoken.freezingScreen
-                                        + " mAppFreezing=" + w.mAppFreezing);
-                                mInnerFields.mTokenMayBeDrawn = true;
-                            }
-                        }
-                    } else if (w.isDrawnLw()) {
-                        atoken.startingDisplayed = true;
-                    }
-                }
-            } else if (w.mReadyToShow) {
-                w.performShowLocked();
-                changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-            }
-        } // end forall windows
-
-        return changes;
-    }
-
-    /**
-     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     *
-     * @return bitmap indicating if another pass through layout must be made.
-     */
-    private int testTokenMayBeDrawnLocked() {
-        int changes = 0;
-        // See if any windows have been drawn, so they (and others
-        // associated with them) can now be shown.
-        final int NT = mAppTokens.size();
-        for (int i=0; i<NT; i++) {
-            AppWindowToken wtoken = mAppTokens.get(i);
-            if (wtoken.freezingScreen) {
-                int numInteresting = wtoken.numInterestingWindows;
-                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
-                    if (DEBUG_VISIBILITY) Slog.v(TAG,
-                            "allDrawn: " + wtoken
-                            + " interesting=" + numInteresting
-                            + " drawn=" + wtoken.numDrawnWindows);
-                    wtoken.showAllWindowsLocked();
-                    unsetAppFreezingScreenLocked(wtoken, false, true);
-                    if (DEBUG_ORIENTATION) Slog.i(TAG,
-                            "Setting mOrientationChangeComplete=true because wtoken "
-                            + wtoken + " numInteresting=" + numInteresting
-                            + " numDrawn=" + wtoken.numDrawnWindows);
-                    mInnerFields.mOrientationChangeComplete = true;
-                }
-            } else if (!wtoken.allDrawn) {
-                int numInteresting = wtoken.numInterestingWindows;
-                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
-                    if (DEBUG_VISIBILITY) Slog.v(TAG,
-                            "allDrawn: " + wtoken
-                            + " interesting=" + numInteresting
-                            + " drawn=" + wtoken.numDrawnWindows);
-                    wtoken.allDrawn = true;
-                    changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
-
-                    // We can now show all of the drawn windows!
-                    if (!mOpeningApps.contains(wtoken)) {
-                        mInnerFields.mAnimating |= wtoken.showAllWindowsLocked();
-                    }
-                }
-            }
-        }
-
-        return changes;
-    }
-
-    /**
-     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
      *
      * @return bitmap indicating if another pass through layout must be made.
      */
@@ -8119,11 +7918,15 @@
                 animLp = null;
             }
 
+            AppWindowToken topOpeningApp = null;
+            int topOpeningLayer = 0;
+
             NN = mOpeningApps.size();
             for (i=0; i<NN; i++) {
                 AppWindowToken wtoken = mOpeningApps.get(i);
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                         "Now opening app" + wtoken);
+                wtoken.clearThumbnail();
                 wtoken.reportedVisible = false;
                 wtoken.inPendingTransaction = false;
                 wtoken.animation = null;
@@ -8131,13 +7934,27 @@
                         transit, false);
                 wtoken.updateReportedVisibilityLocked();
                 wtoken.waitingToShow = false;
-                mInnerFields.mAnimating |= wtoken.showAllWindowsLocked();
+                mAnimator.mAnimating |= wtoken.showAllWindowsLocked();
+                if (animLp != null) {
+                    int layer = -1;
+                    for (int j=0; j<wtoken.windows.size(); j++) {
+                        WindowState win = wtoken.windows.get(j);
+                        if (win.mAnimLayer > layer) {
+                            layer = win.mAnimLayer;
+                        }
+                    }
+                    if (topOpeningApp == null || layer > topOpeningLayer) {
+                        topOpeningApp = wtoken;
+                        topOpeningLayer = layer;
+                    }
+                }
             }
             NN = mClosingApps.size();
             for (i=0; i<NN; i++) {
                 AppWindowToken wtoken = mClosingApps.get(i);
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                         "Now closing app" + wtoken);
+                wtoken.clearThumbnail();
                 wtoken.inPendingTransaction = false;
                 wtoken.animation = null;
                 setTokenVisibilityLocked(wtoken, animLp, false,
@@ -8150,7 +7967,47 @@
                 wtoken.allDrawn = true;
             }
 
+            if (mNextAppTransitionThumbnail != null && topOpeningApp != null
+                    && topOpeningApp.animation != null) {
+                // This thumbnail animation is very special, we need to have
+                // an extra surface with the thumbnail included with the animation.
+                Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(),
+                        mNextAppTransitionThumbnail.getHeight());
+                try {
+                    Surface surface = new Surface(mFxSession, Process.myPid(),
+                            "thumbnail anim", 0, dirty.width(), dirty.height(),
+                            PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                    topOpeningApp.thumbnail = surface;
+                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL "
+                            + surface + ": CREATE");
+                    Surface drawSurface = new Surface();
+                    drawSurface.copyFrom(surface);
+                    Canvas c = drawSurface.lockCanvas(dirty);
+                    c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null);
+                    drawSurface.unlockCanvasAndPost(c);
+                    drawSurface.release();
+                    topOpeningApp.thumbnailLayer = topOpeningLayer;
+                    Animation anim = createThumbnailAnimationLocked(transit, true, true);
+                    topOpeningApp.thumbnailAnimation = anim;
+                    anim.restrictDuration(MAX_ANIMATION_DURATION);
+                    anim.scaleCurrentDuration(mTransitionAnimationScale);
+                    topOpeningApp.thumbnailX = mNextAppTransitionStartX;
+                    topOpeningApp.thumbnailY = mNextAppTransitionStartY;
+                } catch (Surface.OutOfResourcesException e) {
+                    Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
+                            + " h=" + dirty.height(), e);
+                    topOpeningApp.clearThumbnail();
+                }
+            }
+
             mNextAppTransitionPackage = null;
+            mNextAppTransitionThumbnail = null;
+            if (mNextAppTransitionCallback != null) {
+                try {
+                    mNextAppTransitionCallback.sendResult(null);
+                } catch (RemoteException e) {
+                }
+            }
 
             mOpeningApps.clear();
             mClosingApps.clear();
@@ -8229,14 +8086,14 @@
         if (mLowerWallpaperTarget == null) {
             // Whoops, we don't need a special wallpaper animation.
             // Clear them out.
-            mInnerFields.mForceHiding = false;
+            mAnimator.mForceHiding = false;
             for (int i=mWindows.size()-1; i>=0; i--) {
                 WindowState w = mWindows.get(i);
                 if (w.mSurface != null) {
                     final WindowManager.LayoutParams attrs = w.mAttrs;
                     if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
                         if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
-                        mInnerFields.mForceHiding = true;
+                        mAnimator.mForceHiding = true;
                     } else if (mPolicy.canBeForceHidden(w, attrs)) {
                         if (!w.mAnimating) {
                             // We set the animation above so it
@@ -8267,11 +8124,11 @@
             mInnerFields.mWallpaperMayChange = true;
         }
 
-        if (mInnerFields.mWindowAnimationBackgroundColor != 0) {
+        if (mAnimator.mWindowAnimationBackgroundColor != 0) {
             // If the window that wants black is the current wallpaper
             // target, then the black goes *below* the wallpaper so we
             // don't cause the wallpaper to suddenly disappear.
-            WindowState target = mInnerFields.mWindowAnimationBackground;
+            WindowState target = mAnimator.mWindowAnimationBackground;
             if (mWallpaperTarget == target
                     || mLowerWallpaperTarget == target
                     || mUpperWallpaperTarget == target) {
@@ -8290,7 +8147,7 @@
             final int dh = mCurDisplayHeight;
             mWindowAnimationBackgroundSurface.show(dw, dh,
                     target.mAnimLayer - LAYER_OFFSET_DIM,
-                    mInnerFields.mWindowAnimationBackgroundColor);
+                    mAnimator.mWindowAnimationBackgroundColor);
         } else if (mWindowAnimationBackgroundSurface != null) {
             mWindowAnimationBackgroundSurface.hide();
         }
@@ -8393,206 +8250,6 @@
     /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
      *
-     * @param w WindowState whos Surface is being prepared.
-     * @param recoveringMemory true if the caller will reclaim surface memory on error.
-     */
-    public void prepareSurfaceLocked(final WindowState w, final boolean recoveringMemory) {
-        // XXX NOTE: The logic here could be improved.  We have
-        // the decision about whether to resize a window separated
-        // from whether to hide the surface.  This can cause us to
-        // resize a surface even if we are going to hide it.  You
-        // can see this by (1) holding device in landscape mode on
-        // home screen; (2) tapping browser icon (device will rotate
-        // to landscape; (3) tap home.  The wallpaper will be resized
-        // in step 2 but then immediately hidden, causing us to
-        // have to resize and then redraw it again in step 3.  It
-        // would be nice to figure out how to avoid this, but it is
-        // difficult because we do need to resize surfaces in some
-        // cases while they are hidden such as when first showing a
-        // window.
-        
-        if (w.mSurface == null) {
-            if (w.mOrientationChanging) {
-                if (DEBUG_ORIENTATION) {
-                    Slog.v(TAG, "Orientation change skips hidden " + w);
-                }
-                w.mOrientationChanging = false;
-            }
-            return;
-        }
-        
-        boolean displayed = false;
-
-        w.computeShownFrameLocked();
-
-        int width, height;
-        if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
-            // for a scaled surface, we just want to use
-            // the requested size.
-            width  = w.mRequestedWidth;
-            height = w.mRequestedHeight;
-        } else {
-            width = w.mCompatFrame.width();
-            height = w.mCompatFrame.height();
-        }
-
-        if (width < 1) {
-            width = 1;
-        }
-        if (height < 1) {
-            height = 1;
-        }
-        final boolean surfaceResized = w.mSurfaceW != width || w.mSurfaceH != height;
-        if (surfaceResized) {
-            w.mSurfaceW = width;
-            w.mSurfaceH = height;
-        }
-
-        if (w.mSurfaceX != w.mShownFrame.left
-                || w.mSurfaceY != w.mShownFrame.top) {
-            try {
-                if (SHOW_TRANSACTIONS) logSurface(w,
-                        "POS " + w.mShownFrame.left
-                        + ", " + w.mShownFrame.top, null);
-                w.mSurfaceX = w.mShownFrame.left;
-                w.mSurfaceY = w.mShownFrame.top;
-                w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Error positioning surface of " + w
-                        + " pos=(" + w.mShownFrame.left
-                        + "," + w.mShownFrame.top + ")", e);
-                if (!recoveringMemory) {
-                    reclaimSomeSurfaceMemoryLocked(w, "position", true);
-                }
-            }
-        }
-
-        if (surfaceResized) {
-            try {
-                if (SHOW_TRANSACTIONS) logSurface(w,
-                        "SIZE " + width + "x" + height, null);
-                w.mSurfaceResized = true;
-                w.mSurface.setSize(width, height);
-            } catch (RuntimeException e) {
-                // If something goes wrong with the surface (such
-                // as running out of memory), don't take down the
-                // entire system.
-                Slog.e(TAG, "Error resizing surface of " + w
-                        + " size=(" + width + "x" + height + ")", e);
-                if (!recoveringMemory) {
-                    reclaimSomeSurfaceMemoryLocked(w, "size", true);
-                }
-            }
-        }
-
-        updateResizingWindows(w);
-
-        if (w.mAttachedHidden || !w.isReadyForDisplay()) {
-            if (!w.mLastHidden) {
-                //dump();
-                w.mLastHidden = true;
-                if (SHOW_TRANSACTIONS) logSurface(w,
-                        "HIDE (performLayout)", null);
-                if (w.mSurface != null) {
-                    w.mSurfaceShown = false;
-                    try {
-                        w.mSurface.hide();
-                    } catch (RuntimeException e) {
-                        Slog.w(TAG, "Exception hiding surface in " + w);
-                    }
-                }
-            }
-            // If we are waiting for this window to handle an
-            // orientation change, well, it is hidden, so
-            // doesn't really matter.  Note that this does
-            // introduce a potential glitch if the window
-            // becomes unhidden before it has drawn for the
-            // new orientation.
-            if (w.mOrientationChanging) {
-                w.mOrientationChanging = false;
-                if (DEBUG_ORIENTATION) Slog.v(TAG,
-                        "Orientation change skips hidden " + w);
-            }
-        } else if (w.mLastLayer != w.mAnimLayer
-                || w.mLastAlpha != w.mShownAlpha
-                || w.mLastDsDx != w.mDsDx
-                || w.mLastDtDx != w.mDtDx
-                || w.mLastDsDy != w.mDsDy
-                || w.mLastDtDy != w.mDtDy
-                || w.mLastHScale != w.mHScale
-                || w.mLastVScale != w.mVScale
-                || w.mLastHidden) {
-            displayed = true;
-            w.mLastAlpha = w.mShownAlpha;
-            w.mLastLayer = w.mAnimLayer;
-            w.mLastDsDx = w.mDsDx;
-            w.mLastDtDx = w.mDtDx;
-            w.mLastDsDy = w.mDsDy;
-            w.mLastDtDy = w.mDtDy;
-            w.mLastHScale = w.mHScale;
-            w.mLastVScale = w.mVScale;
-            if (SHOW_TRANSACTIONS) logSurface(w,
-                    "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
-                    + " matrix=[" + (w.mDsDx*w.mHScale)
-                    + "," + (w.mDtDx*w.mVScale)
-                    + "][" + (w.mDsDy*w.mHScale)
-                    + "," + (w.mDtDy*w.mVScale) + "]", null);
-            if (w.mSurface != null) {
-                try {
-                    w.mSurfaceAlpha = w.mShownAlpha;
-                    w.mSurface.setAlpha(w.mShownAlpha);
-                    w.mSurfaceLayer = w.mAnimLayer;
-                    w.mSurface.setLayer(w.mAnimLayer);
-                    w.mSurface.setMatrix(
-                            w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
-                            w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
-                } catch (RuntimeException e) {
-                    Slog.w(TAG, "Error updating surface in " + w, e);
-                    if (!recoveringMemory) {
-                        reclaimSomeSurfaceMemoryLocked(w, "update", true);
-                    }
-                }
-            }
-
-            if (w.mLastHidden && w.isDrawnLw()
-                    && !w.mReadyToShow) {
-                if (SHOW_TRANSACTIONS) logSurface(w,
-                        "SHOW (performLayout)", null);
-                if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
-                        + " during relayout");
-                if (showSurfaceRobustlyLocked(w)) {
-                    w.mHasDrawn = true;
-                    w.mLastHidden = false;
-                } else {
-                    w.mOrientationChanging = false;
-                }
-            }
-            if (w.mSurface != null) {
-                w.mToken.hasVisible = true;
-            }
-        } else {
-            displayed = true;
-        }
-
-        if (displayed) {
-            if (w.mOrientationChanging) {
-                if (!w.isDrawnLw()) {
-                    mInnerFields.mOrientationChangeComplete = false;
-                    if (DEBUG_ORIENTATION) Slog.v(TAG,
-                            "Orientation continue waiting for draw in " + w);
-                } else {
-                    w.mOrientationChanging = false;
-                    if (DEBUG_ORIENTATION) Slog.v(TAG,
-                            "Orientation change complete in " + w);
-                }
-            }
-            w.mToken.hasVisible = true;
-        }
-    }
-
-    /**
-     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
-     *
      * @param w WindowState this method is applied to.
      * @param currentTime The time which animations use for calculating transitions.
      * @param innerDw Width of app window.
@@ -8649,65 +8306,6 @@
         }
     }
 
-    private final int performAnimationsLocked(long currentTime, int dw, int dh,
-            int innerDw, int innerDh) {
-        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
-                + mTransactionSequence + " mAnimating="
-                + mInnerFields.mAnimating);
-
-        mInnerFields.mTokenMayBeDrawn = false;
-        mInnerFields.mWallpaperMayChange = false;
-        mInnerFields.mForceHiding = false;
-        mInnerFields.mDetachedWallpaper = null;
-        mInnerFields.mWindowAnimationBackground = null;
-        mInnerFields.mWindowAnimationBackgroundColor = 0;
-
-        int changes = updateWindowsAndWallpaperLocked(currentTime, dw, dh, innerDw, innerDh);
-
-        if (mInnerFields.mTokenMayBeDrawn) {
-            changes |= testTokenMayBeDrawnLocked();
-        }
-
-        // If we are ready to perform an app transition, check through
-        // all of the app tokens to be shown and see if they are ready
-        // to go.
-        if (mAppTransitionReady) {
-            changes |= handleAppTransitionReadyLocked();
-        }
-
-        mInnerFields.mAdjResult = 0;
-
-        if (!mInnerFields.mAnimating && mAppTransitionRunning) {
-            // We have finished the animation of an app transition.  To do
-            // this, we have delayed a lot of operations like showing and
-            // hiding apps, moving apps in Z-order, etc.  The app token list
-            // reflects the correct Z-order, but the window list may now
-            // be out of sync with it.  So here we will just rebuild the
-            // entire app window list.  Fun!
-            changes |= handleAnimatingStoppedAndTransitionLocked();
-        }
-
-        if (mInnerFields.mWallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
-            // At this point, there was a window with a wallpaper that
-            // was force hiding other windows behind it, but now it
-            // is going away.  This may be simple -- just animate
-            // away the wallpaper and its window -- or it may be
-            // hard -- the wallpaper now needs to be shown behind
-            // something that was hidden.
-            changes |= animateAwayWallpaperLocked();
-        }
-
-        changes |= testWallpaperAndBackgroundLocked();
-
-        if (mLayoutNeeded) {
-            changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
-        }
-
-        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
-                + Integer.toHexString(changes));
-        return changes;
-    }
-
     // "Something has changed!  Let's make it correct now."
     private final void performLayoutAndPlaceSurfacesLockedInner(
             boolean recoveringMemory) {
@@ -8745,7 +8343,7 @@
         mInnerFields.mScreenBrightness = -1;
         mInnerFields.mButtonBrightness = -1;
         boolean focusDisplayed = false;
-        mInnerFields.mAnimating = false;
+        mAnimator.mAnimating = false;
         boolean createWatermark = false;
 
         if (mFxSession == null) {
@@ -8786,6 +8384,7 @@
                         mLayoutNeeded = true;
                     }
                 }
+
                 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
                     if (updateOrientationFromAppTokensLocked(true)) {
@@ -8793,6 +8392,7 @@
                         mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
                     }
                 }
+
                 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
                     mLayoutNeeded = true;
                 }
@@ -8855,9 +8455,53 @@
             Surface.closeTransaction();
         }
 
+        // If we are ready to perform an app transition, check through
+        // all of the app tokens to be shown and see if they are ready
+        // to go.
+        if (mAppTransitionReady) {
+            mPendingLayoutChanges |= handleAppTransitionReadyLocked();
+        }
+
+        mInnerFields.mAdjResult = 0;
+
+        if (!mAnimator.mAnimating && mAppTransitionRunning) {
+            // We have finished the animation of an app transition.  To do
+            // this, we have delayed a lot of operations like showing and
+            // hiding apps, moving apps in Z-order, etc.  The app token list
+            // reflects the correct Z-order, but the window list may now
+            // be out of sync with it.  So here we will just rebuild the
+            // entire app window list.  Fun!
+            mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
+        }
+
+        if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 &&
+                !mAppTransitionReady) {
+            // At this point, there was a window with a wallpaper that
+            // was force hiding other windows behind it, but now it
+            // is going away.  This may be simple -- just animate
+            // away the wallpaper and its window -- or it may be
+            // hard -- the wallpaper now needs to be shown behind
+            // something that was hidden.
+            mPendingLayoutChanges |= animateAwayWallpaperLocked();
+        }
+
+        mPendingLayoutChanges |= testWallpaperAndBackgroundLocked();
+
+        if (mLayoutNeeded) {
+            mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+        }
+
+        final int N = mWindows.size();
+        for (i=N-1; i>=0; i--) {
+            WindowState w = mWindows.get(i);
+            // TODO(cmautner): Can this move up to the loop at the end of try/catch above?
+            updateResizingWindows(w);
+        }
+
         // Update animations of all applications, including those
         // associated with exiting/removed apps
-        animateAndUpdateSurfaces(currentTime, dw, dh, innerDw, innerDh, recoveringMemory);
+        mAnimator.animate();
+        mPendingLayoutChanges |= mAnimator.mPendingLayoutChanges;
 
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
@@ -8950,6 +8594,7 @@
                 // Make sure there is no animation running on this token,
                 // so any windows associated with it will be removed as
                 // soon as their animations are complete
+                token.clearAnimation();
                 token.animation = null;
                 token.animating = false;
                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
@@ -8959,9 +8604,7 @@
             }
         }
 
-        boolean needRelayout = false;
-
-        if (!mInnerFields.mAnimating && mAppTransitionRunning) {
+        if (!mAnimator.mAnimating && mAppTransitionRunning) {
             // We have finished the animation of an app transition.  To do
             // this, we have delayed a lot of operations like showing and
             // hiding apps, moving apps in Z-order, etc.  The app token list
@@ -8969,7 +8612,7 @@
             // be out of sync with it.  So here we will just rebuild the
             // entire app window list.  Fun!
             mAppTransitionRunning = false;
-            needRelayout = true;
+            mLayoutNeeded = true;
             rebuildAppWindowListLocked();
             assignLayersLocked();
             // Clear information about apps that were moving.
@@ -8980,19 +8623,10 @@
             mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
         }
         if (wallpaperDestroyed) {
-            needRelayout = adjustWallpaperWindowsLocked() != 0;
+            mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0;
         }
-        if ((mPendingLayoutChanges & (
-                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER |
-                ADJUST_WALLPAPER_LAYERS_CHANGED |
-                WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG |
-                WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
-            needRelayout = true;
-        }
-        if (needRelayout) {
-            requestTraversalLocked();
-        } else if (mInnerFields.mAnimating) {
-            scheduleAnimationLocked();
+        if (mPendingLayoutChanges != 0) {
+            mLayoutNeeded = true;
         }
 
         // Finally update all input windows now that the window changes have stabilized.
@@ -9035,7 +8669,7 @@
             }
         }
 
-        if (mInnerFields.mOrientationChangeComplete && !needRelayout &&
+        if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded &&
                 !mInnerFields.mUpdateRotation) {
             checkDrawnWindowsLocked();
         }
@@ -9257,6 +8891,7 @@
                 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
             final WindowState oldFocus = mCurrentFocus;
             mCurrentFocus = newFocus;
+            mAnimator.setCurrentFocus(mCurrentFocus);
             mLosingFocus.remove(newFocus);
             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
 
@@ -9388,6 +9023,7 @@
         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
             mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
             mNextAppTransitionPackage = null;
+            mNextAppTransitionThumbnail = null;
             mAppTransitionReady = true;
         }
 
@@ -9397,16 +9033,16 @@
         }
 
         if (CUSTOM_SCREEN_ROTATION) {
-            if (mScreenRotationAnimation != null) {
-                mScreenRotationAnimation.kill();
-                mScreenRotationAnimation = null;
+            if (mAnimator.mScreenRotationAnimation != null) {
+                mAnimator.mScreenRotationAnimation.kill();
+                mAnimator.mScreenRotationAnimation = null;
             }
-            if (mScreenRotationAnimation == null) {
-                mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
+            if (mAnimator.mScreenRotationAnimation == null) {
+                mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
                         mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
                         mDisplay.getRotation());
             }
-            if (!mScreenRotationAnimation.hasScreenshot()) {
+            if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) {
                 Surface.freezeDisplay(0);
             }
         } else {
@@ -9431,20 +9067,20 @@
 
         boolean updateRotation = false;
         
-        if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
-                && mScreenRotationAnimation.hasScreenshot()) {
+        if (CUSTOM_SCREEN_ROTATION && mAnimator.mScreenRotationAnimation != null
+                && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
-            if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
+            if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
                     mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) {
                 scheduleAnimationLocked();
             } else {
-                mScreenRotationAnimation = null;
+                mAnimator.mScreenRotationAnimation = null;
                 updateRotation = true;
             }
         } else {
-            if (mScreenRotationAnimation != null) {
-                mScreenRotationAnimation.kill();
-                mScreenRotationAnimation = null;
+            if (mAnimator.mScreenRotationAnimation != null) {
+                mAnimator.mScreenRotationAnimation.kill();
+                mAnimator.mScreenRotationAnimation = null;
             }
             updateRotation = true;
         }
@@ -9927,9 +9563,9 @@
             pw.print("  mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation);
                     pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
             pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
-            if (mScreenRotationAnimation != null) {
+            if (mAnimator.mScreenRotationAnimation != null) {
                 pw.println("  mScreenRotationAnimation:");
-                mScreenRotationAnimation.printTo("    ", pw);
+                mAnimator.mScreenRotationAnimation.printTo("    ", pw);
             }
             pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
                     pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
@@ -9948,6 +9584,12 @@
                     pw.print(" mNextAppTransitionExit=0x");
                     pw.print(Integer.toHexString(mNextAppTransitionExit));
             }
+            if (mNextAppTransitionThumbnail != null) {
+                pw.print("  mNextAppTransitionThumbnail=");
+                    pw.print(mNextAppTransitionThumbnail);
+                    pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
+                    pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY);
+            }
             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
                     pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
         }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index d1a14df3..cf61f7f 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -1227,8 +1227,8 @@
             }
         }
 
-        final boolean screenAnimation = mService.mScreenRotationAnimation != null
-                && mService.mScreenRotationAnimation.isAnimating();
+        final boolean screenAnimation = mService.mAnimator.mScreenRotationAnimation != null
+                && mService.mAnimator.mScreenRotationAnimation.isAnimating();
         if (selfTransformation || attachedTransformation != null
                 || appTransformation != null || screenAnimation) {
             // cache often used attributes locally
@@ -1268,7 +1268,7 @@
             }
             if (screenAnimation) {
                 tmpMatrix.postConcat(
-                        mService.mScreenRotationAnimation.getEnterTransformation().getMatrix());
+                        mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getMatrix());
             }
 
             // "convert" it into SurfaceFlinger's format
@@ -1311,7 +1311,7 @@
                 }
                 if (screenAnimation) {
                     mShownAlpha *=
-                        mService.mScreenRotationAnimation.getEnterTransformation().getAlpha();
+                        mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha();
                 }
             } else {
                 //Slog.i(TAG, "Not applying alpha transform");
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
new file mode 100644
index 0000000..796372d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -0,0 +1,205 @@
+/*
+ * 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.server.pm;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+
+import com.android.internal.content.PackageHelper;
+import com.android.internal.os.AtomicFile;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashSet;
+
+import android.os.Debug;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.storage.IMountService;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+public class PackageManagerSettingsTests extends AndroidTestCase {
+
+    private static final String PACKAGE_NAME_2 = "com.google.app2";
+    private static final String PACKAGE_NAME_3 = "com.android.app3";
+    private static final String PACKAGE_NAME_1 = "com.google.app1";
+    private static final boolean localLOGV = true;
+    public static final String TAG = "PackageManagerSettingsTests";
+    protected final String PREFIX = "android.content.pm";
+
+    private void writeFile(File file, byte[] data) {
+        file.mkdirs();
+        try {
+            AtomicFile aFile = new AtomicFile(file);
+            FileOutputStream fos = aFile.startWrite();
+            fos.write(data);
+            aFile.finishWrite(fos);
+        } catch (IOException ioe) {
+            Log.e(TAG, "Cannot write file " + file.getPath());
+        }
+    }
+
+    private void writePackagesXml() {
+        writeFile(new File(getContext().getFilesDir(), "system/packages.xml"),
+                ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+                + "<packages>"
+                + "<last-platform-version internal=\"15\" external=\"0\" />"
+                + "<permission-trees>"
+                + "<item name=\"com.google.android.permtree\" package=\"com.google.android.permpackage\" />"
+                + "</permission-trees>"
+                + "<permissions>"
+                + "<item name=\"android.permission.WRITE_CALL_LOG\" package=\"android\" protection=\"1\" />"
+                + "<item name=\"android.permission.ASEC_ACCESS\" package=\"android\" protection=\"2\" />"
+                + "<item name=\"android.permission.ACCESS_WIMAX_STATE\" package=\"android\" />"
+                + "<item name=\"android.permission.REBOOT\" package=\"android\" protection=\"18\" />"
+                + "</permissions>"
+                + "<package name=\"com.google.app1\" codePath=\"/system/app/app1.apk\" nativeLibraryPath=\"/data/data/com.google.app1/lib\" flags=\"1\" ft=\"1360e2caa70\" it=\"135f2f80d08\" ut=\"1360e2caa70\" version=\"1109\" sharedUserId=\"11000\">"
+                + "<sigs count=\"1\">"
+                + "<cert index=\"0\" key=\"308886\" />"
+                + "</sigs>"
+                + "</package>"
+                + "<package name=\"com.google.app2\" codePath=\"/system/app/app2.apk\" nativeLibraryPath=\"/data/data/com.google.app2/lib\" flags=\"1\" ft=\"1360e578718\" it=\"135f2f80d08\" ut=\"1360e578718\" version=\"15\" enabled=\"3\" userId=\"11001\">"
+                + "<sigs count=\"1\">"
+                + "<cert index=\"0\" />"
+                + "</sigs>"
+                + "</package>"
+                + "<package name=\"com.android.app3\" codePath=\"/system/app/app3.apk\" nativeLibraryPath=\"/data/data/com.android.app3/lib\" flags=\"1\" ft=\"1360e577b60\" it=\"135f2f80d08\" ut=\"1360e577b60\" version=\"15\" userId=\"11030\">"
+                + "<sigs count=\"1\">"
+                + "<cert index=\"1\" key=\"308366\" />"
+                + "</sigs>"
+                + "</package>"
+                + "<shared-user name=\"com.android.shared1\" userId=\"11000\">"
+                + "<sigs count=\"1\">"
+                + "<cert index=\"1\" />"
+                + "</sigs>"
+                + "<perms>"
+                + "<item name=\"android.permission.REBOOT\" />"
+                + "</perms>"
+                + "</shared-user>"
+                + "</packages>").getBytes());
+    }
+
+    private void writeStoppedPackagesXml() {
+        writeFile(new File(getContext().getFilesDir(), "system/packages-stopped.xml"),
+                ( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+                + "<stopped-packages>"
+                + "<pkg name=\"com.google.app1\" nl=\"1\" />"
+                + "<pkg name=\"com.android.app3\" nl=\"1\" />"
+                + "</stopped-packages>")
+                .getBytes());
+    }
+
+    private void writePackagesList() {
+        writeFile(new File(getContext().getFilesDir(), "system/packages.list"),
+                ( "com.google.app1 11000 0 /data/data/com.google.app1"
+                + "com.google.app2 11001 0 /data/data/com.google.app2"
+                + "com.android.app3 11030 0 /data/data/com.android.app3")
+                .getBytes());
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    private void writeOldFiles() {
+        writePackagesXml();
+        writeStoppedPackagesXml();
+        writePackagesList();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testSettingsReadOld() {
+        // Debug.waitForDebugger();
+
+        // Write the package files and make sure they're parsed properly the first time
+        writeOldFiles();
+        Settings settings = new Settings(getContext().getFilesDir());
+        assertEquals(true, settings.readLPw(null));
+        assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
+        assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
+
+        PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
+        assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(0));
+        assertEquals(true, ps.getNotLaunched(0));
+
+        ps = settings.peekPackageLPr(PACKAGE_NAME_2);
+        assertEquals(false, ps.getStopped(0));
+        assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
+        assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(1));
+    }
+
+    public void testNewPackageRestrictionsFile() {
+        // Write the package files and make sure they're parsed properly the first time
+        writeOldFiles();
+        Settings settings = new Settings(getContext().getFilesDir());
+        assertEquals(true, settings.readLPw(null));
+
+        // Create Settings again to make it read from the new files
+        settings = new Settings(getContext().getFilesDir());
+        assertEquals(true, settings.readLPw(null));
+
+        PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
+        assertEquals(COMPONENT_ENABLED_STATE_DISABLED_USER, ps.getEnabled(0));
+        assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(1));
+    }
+
+    public void testEnableDisable() {
+        // Write the package files and make sure they're parsed properly the first time
+        writeOldFiles();
+        Settings settings = new Settings(getContext().getFilesDir());
+        assertEquals(true, settings.readLPw(null));
+
+        // Enable/Disable a package
+        PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
+        ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0);
+        ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1);
+        assertEquals(COMPONENT_ENABLED_STATE_DISABLED, ps.getEnabled(0));
+        assertEquals(COMPONENT_ENABLED_STATE_ENABLED, ps.getEnabled(1));
+
+        // Enable/Disable a component
+        HashSet<String> components = new HashSet<String>();
+        String component1 = PACKAGE_NAME_1 + "/.Component1";
+        components.add(component1);
+        ps.setDisabledComponents(components, 0);
+        HashSet<String> componentsDisabled = ps.getDisabledComponents(0);
+        assertEquals(1, componentsDisabled.size());
+        assertEquals(component1, componentsDisabled.toArray()[0]);
+        boolean hasEnabled =
+                ps.getEnabledComponents(0) != null && ps.getEnabledComponents(1).size() > 0;
+        assertEquals(false, hasEnabled);
+
+        // User 1 should not have any disabled components
+        boolean hasDisabled =
+                ps.getDisabledComponents(1) != null && ps.getDisabledComponents(1).size() > 0;
+        assertEquals(false, hasDisabled);
+        ps.setEnabledComponents(components, 1);
+        assertEquals(1, ps.getEnabledComponents(1).size());
+        hasEnabled = ps.getEnabledComponents(0) != null && ps.getEnabledComponents(0).size() > 0;
+        assertEquals(false, hasEnabled);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index 7ae6692..2139917 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -37,6 +37,7 @@
 import com.android.internal.telephony.CommandsInterface.RadioState;
 import com.android.internal.telephony.gsm.SIMFileHandler;
 import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.cat.CatService;
 import com.android.internal.telephony.cdma.CDMALTEPhone;
 import com.android.internal.telephony.cdma.CdmaLteUiccFileHandler;
 import com.android.internal.telephony.cdma.CdmaLteUiccRecords;
@@ -65,6 +66,8 @@
     protected PhoneBase mPhone;
     private IccRecords mIccRecords;
     private IccFileHandler mIccFileHandler;
+    private CatService mCatService;
+
     private RegistrantList mAbsentRegistrants = new RegistrantList();
     private RegistrantList mPinLockedRegistrants = new RegistrantList();
     private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
@@ -194,6 +197,8 @@
             mIccRecords = is3gpp ? new SIMRecords(this, mPhone.mContext, mPhone.mCM) :
                                    new RuimRecords(this, mPhone.mContext, mPhone.mCM);
         }
+        mCatService = CatService.getInstance(mPhone.mCM, mIccRecords,
+                mPhone.mContext, mIccFileHandler, this);
         mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         mPhone.mCM.registerForOn(mHandler, EVENT_RADIO_ON, null);
         mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_STATUS_CHANGED, null);
@@ -204,6 +209,7 @@
         mPhone.mCM.unregisterForIccStatusChanged(mHandler);
         mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
         mPhone.mCM.unregisterForOn(mHandler);
+        mCatService.dispose();
         mCdmaSSM.dispose(mHandler);
         mIccRecords.dispose();
         mIccFileHandler.dispose();
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 9e4a735..ce581de 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -103,7 +103,6 @@
     PhoneSubInfo mSubInfo;
     EriManager mEriManager;
     WakeLock mWakeLock;
-    CatService mCcatService;
 
     // mEriFileLoadedRegistrants are informed after the ERI text has been loaded
     private final RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
@@ -169,8 +168,6 @@
         mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
         mSubInfo = new PhoneSubInfo(this);
         mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
-        mCcatService = CatService.getInstance(mCM, mIccRecords, mContext,
-                mIccFileHandler, mIccCard);
 
         mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         registerForRuimRecordEvents();
@@ -245,14 +242,12 @@
             mRuimSmsInterfaceManager.dispose();
             mSubInfo.dispose();
             mEriManager.dispose();
-            mCcatService.dispose();
         }
     }
 
     @Override
     public void removeReferences() {
         log("removeReferences");
-        super.removeReferences();
         mRuimPhoneBookInterfaceManager = null;
         mRuimSmsInterfaceManager = null;
         mSubInfo = null;
@@ -260,8 +255,8 @@
         mCT = null;
         mSST = null;
         mEriManager = null;
-        mCcatService = null;
         mExitEcmRunnable = null;
+        super.removeReferences();
     }
 
     @Override
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index 27f362c..6e10542 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -101,7 +101,6 @@
     // Instance Variables
     GsmCallTracker mCT;
     GsmServiceStateTracker mSST;
-    CatService mStkService;
     ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
     SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
     SimSmsInterfaceManager mSimSmsIntManager;
@@ -149,7 +148,6 @@
             mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
             mSubInfo = new PhoneSubInfo(this);
         }
-        mStkService = CatService.getInstance(mCM, mIccRecords, mContext, mIccFileHandler, mIccCard);
 
         mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         registerForSimRecordEvents();
@@ -215,7 +213,6 @@
             mPendingMMIs.clear();
 
             //Force all referenced classes to unregister their former registered events
-            mStkService.dispose();
             mCT.dispose();
             mDataConnectionTracker.dispose();
             mSST.dispose();
@@ -228,15 +225,14 @@
     @Override
     public void removeReferences() {
         Log.d(LOG_TAG, "removeReferences");
-        super.removeReferences();
         mSimulatedRadioControl = null;
-        mStkService = null;
         mSimPhoneBookIntManager = null;
         mSimSmsIntManager = null;
         mSubInfo = null;
         mIccFileHandler = null;
         mCT = null;
         mSST = null;
+        super.removeReferences();
     }
 
     protected void finalize() {
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/mesh.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/mesh.rs
index 627ab99..1354897 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/mesh.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/mesh.rs
@@ -11,29 +11,29 @@
 static bool test_mesh_getters() {
     bool failed = false;
 
-    _RS_ASSERT(rsMeshGetVertexAllocationCount(mesh) == 2);
-    _RS_ASSERT(rsMeshGetPrimitiveCount(mesh) == 3);
+    _RS_ASSERT(rsgMeshGetVertexAllocationCount(mesh) == 2);
+    _RS_ASSERT(rsgMeshGetPrimitiveCount(mesh) == 3);
 
-    rs_allocation meshV0 = rsMeshGetVertexAllocation(mesh, 0);
-    rs_allocation meshV1 = rsMeshGetVertexAllocation(mesh, 1);
-    rs_allocation meshV2 = rsMeshGetVertexAllocation(mesh, 2);
+    rs_allocation meshV0 = rsgMeshGetVertexAllocation(mesh, 0);
+    rs_allocation meshV1 = rsgMeshGetVertexAllocation(mesh, 1);
+    rs_allocation meshV2 = rsgMeshGetVertexAllocation(mesh, 2);
     _RS_ASSERT(meshV0.p == vertexAlloc0.p);
     _RS_ASSERT(meshV1.p == vertexAlloc1.p);
     _RS_ASSERT(!rsIsObject(meshV2));
 
-    rs_allocation meshI0 = rsMeshGetIndexAllocation(mesh, 0);
-    rs_allocation meshI1 = rsMeshGetIndexAllocation(mesh, 1);
-    rs_allocation meshI2 = rsMeshGetIndexAllocation(mesh, 2);
-    rs_allocation meshI3 = rsMeshGetIndexAllocation(mesh, 3);
+    rs_allocation meshI0 = rsgMeshGetIndexAllocation(mesh, 0);
+    rs_allocation meshI1 = rsgMeshGetIndexAllocation(mesh, 1);
+    rs_allocation meshI2 = rsgMeshGetIndexAllocation(mesh, 2);
+    rs_allocation meshI3 = rsgMeshGetIndexAllocation(mesh, 3);
     _RS_ASSERT(meshI0.p == indexAlloc0.p);
     _RS_ASSERT(!rsIsObject(meshI1));
     _RS_ASSERT(meshI2.p == indexAlloc2.p);
     _RS_ASSERT(!rsIsObject(meshI3));
 
-    rs_primitive p0 = rsMeshGetPrimitive(mesh, 0);
-    rs_primitive p1 = rsMeshGetPrimitive(mesh, 1);
-    rs_primitive p2 = rsMeshGetPrimitive(mesh, 2);
-    rs_primitive p3 = rsMeshGetPrimitive(mesh, 3);
+    rs_primitive p0 = rsgMeshGetPrimitive(mesh, 0);
+    rs_primitive p1 = rsgMeshGetPrimitive(mesh, 1);
+    rs_primitive p2 = rsgMeshGetPrimitive(mesh, 2);
+    rs_primitive p3 = rsgMeshGetPrimitive(mesh, 3);
 
     _RS_ASSERT(p0 == RS_PRIMITIVE_POINT);
     _RS_ASSERT(p1 == RS_PRIMITIVE_LINE);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
index 0eaca4a..11b8c30 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
@@ -7,11 +7,11 @@
 static bool test_program_raster_getters() {
     bool failed = false;
 
-    _RS_ASSERT(rsProgramRasterGetPointSpriteEnabled(pointSpriteEnabled) == true);
-    _RS_ASSERT(rsProgramRasterGetCullMode(pointSpriteEnabled) == RS_CULL_BACK);
+    _RS_ASSERT(rsgProgramRasterGetPointSpriteEnabled(pointSpriteEnabled) == true);
+    _RS_ASSERT(rsgProgramRasterGetCullMode(pointSpriteEnabled) == RS_CULL_BACK);
 
-    _RS_ASSERT(rsProgramRasterGetPointSpriteEnabled(cullMode) == false);
-    _RS_ASSERT(rsProgramRasterGetCullMode(cullMode) == RS_CULL_FRONT);
+    _RS_ASSERT(rsgProgramRasterGetPointSpriteEnabled(cullMode) == false);
+    _RS_ASSERT(rsgProgramRasterGetCullMode(cullMode) == RS_CULL_FRONT);
 
     if (failed) {
         rsDebug("test_program_raster_getters FAILED", 0);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
index 7b47408..3cd8a20 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
@@ -14,95 +14,95 @@
 static bool test_program_store_getters() {
     bool failed = false;
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(depthFunc) == RS_DEPTH_FUNC_GREATER);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(depthFunc) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(depthFunc) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(depthFunc) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(depthFunc) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(depthFunc) == false);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(depthFunc) == false);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(depthFunc) == RS_BLEND_SRC_ZERO);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(depthFunc) == RS_BLEND_DST_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthFunc) == RS_DEPTH_FUNC_GREATER);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(depthFunc) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthFunc) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthFunc) == RS_BLEND_DST_ZERO);
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(depthWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(depthWriteEnable) == true);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(depthWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(depthWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(depthWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(depthWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(depthWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(depthWriteEnable) == RS_BLEND_SRC_ZERO);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(depthWriteEnable) == RS_BLEND_DST_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(depthWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(depthWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthWriteEnable) == RS_BLEND_DST_ZERO);
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(colorRWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(colorRWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(colorRWriteEnable) == true);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(colorRWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(colorRWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(colorRWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(colorRWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(colorRWriteEnable) == RS_BLEND_SRC_ZERO);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(colorRWriteEnable) == RS_BLEND_DST_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorRWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorRWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorRWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorRWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorRWriteEnable) == RS_BLEND_DST_ZERO);
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(colorGWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(colorGWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(colorGWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(colorGWriteEnable) == true);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(colorGWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(colorGWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(colorGWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(colorGWriteEnable) == RS_BLEND_SRC_ZERO);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(colorGWriteEnable) == RS_BLEND_DST_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorGWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorGWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorGWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorGWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorGWriteEnable) == RS_BLEND_DST_ZERO);
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(colorBWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(colorBWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(colorBWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(colorBWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(colorBWriteEnable) == true);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(colorBWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(colorBWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(colorBWriteEnable) == RS_BLEND_SRC_ZERO);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(colorBWriteEnable) == RS_BLEND_DST_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorBWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorBWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorBWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorBWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorBWriteEnable) == RS_BLEND_DST_ZERO);
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(colorAWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(colorAWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(colorAWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(colorAWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(colorAWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(colorAWriteEnable) == true);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(colorAWriteEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(colorAWriteEnable) == RS_BLEND_SRC_ZERO);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(colorAWriteEnable) == RS_BLEND_DST_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorAWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorAWriteEnable) == true);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorAWriteEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorAWriteEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorAWriteEnable) == RS_BLEND_DST_ZERO);
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(ditherEnable) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(ditherEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(ditherEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(ditherEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(ditherEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(ditherEnable) == false);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(ditherEnable) == true);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(ditherEnable) == RS_BLEND_SRC_ZERO);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(ditherEnable) == RS_BLEND_DST_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(ditherEnable) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(ditherEnable) == false);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(ditherEnable) == true);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(ditherEnable) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(ditherEnable) == RS_BLEND_DST_ZERO);
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(blendSrc) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(blendSrc) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(blendSrc) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(blendSrc) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(blendSrc) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(blendSrc) == false);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(blendSrc) == false);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(blendSrc) == RS_BLEND_SRC_DST_COLOR);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(blendSrc) == RS_BLEND_DST_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendSrc) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(blendSrc) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendSrc) == RS_BLEND_SRC_DST_COLOR);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendSrc) == RS_BLEND_DST_ZERO);
 
-    _RS_ASSERT(rsProgramStoreGetDepthFunc(blendDst) == RS_DEPTH_FUNC_ALWAYS);
-    _RS_ASSERT(rsProgramStoreGetDepthMask(blendDst) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskR(blendDst) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskG(blendDst) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskB(blendDst) == false);
-    _RS_ASSERT(rsProgramStoreGetColorMaskA(blendDst) == false);
-    _RS_ASSERT(rsProgramStoreGetDitherEnabled(blendDst) == false);
-    _RS_ASSERT(rsProgramStoreGetBlendSrcFunc(blendDst) == RS_BLEND_SRC_ZERO);
-    _RS_ASSERT(rsProgramStoreGetBlendDstFunc(blendDst) == RS_BLEND_DST_DST_ALPHA);
+    _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendDst) == RS_DEPTH_FUNC_ALWAYS);
+    _RS_ASSERT(rsgProgramStoreGetDepthMask(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskR(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskG(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskB(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreGetColorMaskA(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreGetDitherEnabled(blendDst) == false);
+    _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendDst) == RS_BLEND_SRC_ZERO);
+    _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendDst) == RS_BLEND_DST_DST_ALPHA);
 
     if (failed) {
         rsDebug("test_program_store_getters FAILED", 0);
diff --git a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
index 4cacbc4..cceed16 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
@@ -39,7 +39,7 @@
     @SmallTest
 	public void testREORDER_TASKS() {
         try {
-            mAm.moveTaskToFront(0, 0);
+            mAm.moveTaskToFront(0, 0, null);
             fail("IActivityManager.moveTaskToFront did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/aapt/ZipFile.cpp b/tools/aapt/ZipFile.cpp
index 8057068..3994c31 100644
--- a/tools/aapt/ZipFile.cpp
+++ b/tools/aapt/ZipFile.cpp
@@ -20,8 +20,8 @@
 
 #define LOG_TAG "zip"
 
-#include <androidfw/ZipUtils.h>
 #include <utils/Log.h>
+#include <utils/ZipUtils.h>
 
 #include "ZipFile.h"
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index 945b3cd7..5256b58 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -85,15 +85,18 @@
     // ------ Native Delegates ------
 
     @LayoutlibDelegate
-    /*package*/ static void nativeSetDefaultConfig(int nativeConfig) {
-        // pass
+    /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage,
+            Rect padding, Options opts) {
+        return nativeDecodeStream(is, storage, padding, opts, false, 1.f);
     }
 
     @LayoutlibDelegate
-    /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage,
-            Rect padding, Options opts) {
+    /*package*/ static  Bitmap nativeDecodeStream(InputStream is, byte[] storage,
+            Rect padding, Options opts, boolean applyScale, float scale) {
         Bitmap bm = null;
 
+        //TODO support rescaling
+
         Density density = Density.MEDIUM;
         if (opts != null) {
             density = Density.getEnum(opts.inDensity);
@@ -147,6 +150,13 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts,
+            boolean applyScale, float scale) {
+        opts.inBitmap = null;
+        return null;
+    }
+
+    @LayoutlibDelegate
     /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset,
             int length, Options opts) {
         opts.inBitmap = null;
diff --git a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java
new file mode 100644
index 0000000..14b84ef
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.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.view;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link ViewRootImpl}
+ *
+ * Through the layoutlib_create tool, the original  methods of ViewRootImpl have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class ViewRootImpl_Delegate {
+
+    @LayoutlibDelegate
+    /*package*/ static boolean isInTouchMode() {
+        return false; // this allows displaying selection.
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index bef2c95..8b1d41a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -340,6 +340,12 @@
     }
 
     @Override
+    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
+            IRemoteCallback startedCallback) throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
     public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
         // TODO Auto-generated method stub
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 170cd6a..79e02c8 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -114,6 +114,7 @@
         "android.view.LayoutInflater#rInflate",
         "android.view.LayoutInflater#parseInclude",
         "android.view.View#isInEditMode",
+        "android.view.ViewRootImpl#isInTouchMode",
         "android.view.inputmethod.InputMethodManager#getInstance",
         "android.util.Log#println_native",
         "com.android.internal.util.XmlUtils#convertValueToInt",
diff --git a/wifi/java/android/net/wifi/NetworkUpdateResult.java b/wifi/java/android/net/wifi/NetworkUpdateResult.java
index 6b7b68b..234bbe1 100644
--- a/wifi/java/android/net/wifi/NetworkUpdateResult.java
+++ b/wifi/java/android/net/wifi/NetworkUpdateResult.java
@@ -22,6 +22,7 @@
     int netId;
     boolean ipChanged;
     boolean proxyChanged;
+    boolean isNewNetwork = false;
 
     public NetworkUpdateResult(int id) {
         netId = id;
@@ -58,4 +59,12 @@
     public boolean hasProxyChanged() {
         return proxyChanged;
     }
+
+    public boolean isNewNetwork() {
+        return isNewNetwork;
+    }
+
+    public void setIsNewNetwork(boolean isNew) {
+        isNewNetwork = isNew;
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 46ad036..5dec269 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -273,7 +273,8 @@
             mConfiguredNetworks.get(netId).status = Status.ENABLED;
         }
         mWifiNative.saveConfig();
-        sendConfiguredNetworksChangedBroadcast();
+        sendConfiguredNetworksChangedBroadcast(config, result.isNewNetwork() ?
+                WifiManager.CHANGE_REASON_ADDED : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
         return result;
     }
 
@@ -307,13 +308,16 @@
     boolean forgetNetwork(int netId) {
         if (mWifiNative.removeNetwork(netId)) {
             mWifiNative.saveConfig();
+            WifiConfiguration target = null;
             WifiConfiguration config = mConfiguredNetworks.get(netId);
             if (config != null) {
-                mConfiguredNetworks.remove(netId);
+                target = mConfiguredNetworks.remove(netId);
                 mNetworkIds.remove(configKey(config));
             }
-            writeIpAndProxyConfigurations();
-            sendConfiguredNetworksChangedBroadcast();
+            if (target != null) {
+                writeIpAndProxyConfigurations();
+                sendConfiguredNetworksChangedBroadcast(target, WifiManager.CHANGE_REASON_REMOVED);
+            }
             return true;
         } else {
             loge("Failed to remove network " + netId);
@@ -332,7 +336,11 @@
      */
     int addOrUpdateNetwork(WifiConfiguration config) {
         NetworkUpdateResult result = addOrUpdateNetworkNative(config);
-        sendConfiguredNetworksChangedBroadcast();
+        if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
+            sendConfiguredNetworksChangedBroadcast(mConfiguredNetworks.get(result.getNetworkId()),
+                    result.isNewNetwork ? WifiManager.CHANGE_REASON_ADDED :
+                        WifiManager.CHANGE_REASON_CONFIG_CHANGE);
+        }
         return result.getNetworkId();
     }
 
@@ -347,14 +355,17 @@
      */
     boolean removeNetwork(int netId) {
         boolean ret = mWifiNative.removeNetwork(netId);
+        WifiConfiguration config = null;
         if (ret) {
-            WifiConfiguration config = mConfiguredNetworks.get(netId);
+            config = mConfiguredNetworks.get(netId);
             if (config != null) {
-                mConfiguredNetworks.remove(netId);
+                config = mConfiguredNetworks.remove(netId);
                 mNetworkIds.remove(configKey(config));
             }
         }
-        sendConfiguredNetworksChangedBroadcast();
+        if (config != null) {
+            sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
+        }
         return ret;
     }
 
@@ -364,12 +375,24 @@
      * API. The more powerful selectNetwork()/saveNetwork() is used by the
      * state machine for connecting to a network
      *
-     * @param netId network to be removed
+     * @param netId network to be enabled
      * @return {@code true} if it succeeds, {@code false} otherwise
      */
     boolean enableNetwork(int netId, boolean disableOthers) {
         boolean ret = enableNetworkWithoutBroadcast(netId, disableOthers);
-        sendConfiguredNetworksChangedBroadcast();
+        if (disableOthers) {
+            sendConfiguredNetworksChangedBroadcast();
+        } else {
+            WifiConfiguration enabledNetwork = null;
+            synchronized(mConfiguredNetworks) {
+                enabledNetwork = mConfiguredNetworks.get(netId);
+            }
+            // check just in case the network was removed by someone else.
+            if (enabledNetwork != null) {
+                sendConfiguredNetworksChangedBroadcast(enabledNetwork,
+                        WifiManager.CHANGE_REASON_CONFIG_CHANGE);
+            }
+        }
         return ret;
     }
 
@@ -402,13 +425,18 @@
      */
     boolean disableNetwork(int netId, int reason) {
         boolean ret = mWifiNative.disableNetwork(netId);
+        WifiConfiguration network = null;
         WifiConfiguration config = mConfiguredNetworks.get(netId);
         /* Only change the reason if the network was not previously disabled */
         if (config != null && config.status != Status.DISABLED) {
             config.status = Status.DISABLED;
             config.disableReason = reason;
+            network = config;
         }
-        sendConfiguredNetworksChangedBroadcast();
+        if (network != null) {
+            sendConfiguredNetworksChangedBroadcast(network,
+                    WifiManager.CHANGE_REASON_CONFIG_CHANGE);
+        }
         return ret;
     }
 
@@ -574,9 +602,29 @@
         return false;
     }
 
+    /**
+     * Should be called when a single network configuration is made.
+     * @param network The network configuration that changed.
+     * @param reason The reason for the change, should be one of WifiManager.CHANGE_REASON_ADDED,
+     * WifiManager.CHANGE_REASON_REMOVED, or WifiManager.CHANGE_REASON_CHANGE.
+     */
+    private void sendConfiguredNetworksChangedBroadcast(WifiConfiguration network,
+            int reason) {
+        Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false);
+        intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, network);
+        intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason);
+        mContext.sendBroadcast(intent);
+    }
+
+    /**
+     * Should be called when multiple network configuration changes are made.
+     */
     private void sendConfiguredNetworksChangedBroadcast() {
         Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true);
         mContext.sendBroadcast(intent);
     }
 
@@ -1135,6 +1183,7 @@
         mNetworkIds.put(configKey(currentConfig), netId);
 
         NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(currentConfig, config);
+        result.setIsNewNetwork(newNetwork);
         result.setNetworkId(netId);
         return result;
     }
@@ -1234,7 +1283,8 @@
         if (ipChanged || proxyChanged) {
             currentConfig.linkProperties = linkProperties;
             writeIpAndProxyConfigurations();
-            sendConfiguredNetworksChangedBroadcast();
+            sendConfiguredNetworksChangedBroadcast(currentConfig,
+                    WifiManager.CHANGE_REASON_CONFIG_CHANGE);
         }
         return new NetworkUpdateResult(ipChanged, proxyChanged);
     }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index d746810..8aa613b 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -294,12 +294,53 @@
 
     /**
      * Broadcast intent action indicating that the configured networks changed.
-     * This can be as a result of adding/updating/deleting a network
+     * This can be as a result of adding/updating/deleting a network. If
+     * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration
+     * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple
+     * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present.
      * @hide
      */
     public static final String CONFIGURED_NETWORKS_CHANGED_ACTION =
         "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
     /**
+     * The lookup key for a (@link android.net.wifi.WifiConfiguration} object representing
+     * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION}
+     * broadcast is sent.
+     * @hide
+     */
+    public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
+    /**
+     * Multiple network configurations have changed.
+     * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
+     *
+     * @hide
+     */
+    public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
+    /**
+     * The lookup key for an integer indicating the reason a Wi-Fi network configuration
+     * has changed. Only present if {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is {@code false}
+     * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
+     * @hide
+     */
+    public static final String EXTRA_CHANGE_REASON = "changeReason";
+    /**
+     * The configuration is new and was added.
+     * @hide
+     */
+    public static final int CHANGE_REASON_ADDED = 0;
+    /**
+     * The configuration was removed and is no longer present in the system's list of
+     * configured networks.
+     * @hide
+     */
+    public static final int CHANGE_REASON_REMOVED = 1;
+    /**
+     * The configuration has changed as a result of explicit action or because the system
+     * took an automated action such as disabling a malfunctioning configuration.
+     * @hide
+     */
+    public static final int CHANGE_REASON_CONFIG_CHANGE = 2;
+    /**
      * An access point scan has completed, and results are available from the supplicant.
      * Call {@link #getScanResults()} to obtain the results.
      */
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 05a8ca7..cbf7bf8 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -394,7 +394,7 @@
      * Starting and shutting down driver too quick causes problems leading to driver
      * being in a bad state. Delay driver stop.
      */
-    private static final int DELAYED_DRIVER_STOP_MS = 2 * 60 * 1000; /* 2 minutes */
+    private final int mDriverStopDelayMs;
     private int mDelayedStopCounter;
     private boolean mInDelayedStop = false;
 
@@ -563,6 +563,9 @@
         mDefaultSupplicantScanIntervalMs = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_wifi_supplicant_scan_interval);
 
+        mDriverStopDelayMs = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_wifi_driver_stop_delay);
+
         mContext.registerReceiver(
             new BroadcastReceiver() {
                 @Override
@@ -2589,7 +2592,7 @@
                     } else {
                         /* send regular delayed shut down */
                         sendMessageDelayed(obtainMessage(CMD_DELAYED_STOP_DRIVER,
-                                mDelayedStopCounter, 0), DELAYED_DRIVER_STOP_MS);
+                                mDelayedStopCounter, 0), mDriverStopDelayMs);
                     }
                     break;
                 case CMD_START_DRIVER: